如何解决Docker-Deskto上ClickHouse的数据持久化问题
问题背景
Docker-Desktop 版本:4.29.0
受实际硬件条件影响,用于部署数据服务的工作站为Windows11专业版,其中包含两块SSD:
- c盘,操作系统、公共软件的安装,如Docker-Desktop、Navicat...
- d盘,高IO软件、服务的安装部署(磁盘空间大),如PostgreSQL、MySQL...
ClickHouse容器/服务的数据存储/var/lib/clickhouse目录下,往往应用通过Docker化部署时,针对数据部分会执行持久化配置以保证数据的安全性,例如通过宿主机的目录挂载、或者Docker卷(Volume)等形式。
在采用目录挂载的方式时,只需要在docker-compose中指定持久化映射的数据目录即可,例如
./vl-clickhouse/data:/var/lib/clickhouse(其中docker-compose编排配置在指定的目录,如d盘)
但ClickHouse内部对数据组织往往是针对文件的一系列操作,因此当通过目录挂载进行数据持久化时,执行数据导入往往会出现权限问题,如:
bash
Received exception from server (version 23.8.16): Code: 1001. DB::Exception: Received from localhost:9000. DB::Exception: std::__1::__fs::filesystem::filesystem_error: filesystem error: in rename: Permission denied ["/var/lib/clickhouse/store/732/732539d3-dd89-49d0-8fea-510019cd8315/tmp_insert_202505_67_67_0/"] ["/var/lib/clickhouse/store/732/732539d3-dd89-49d0-8fea-510019cd8315/202505_34_34_0/"]. (STD_EXCEPTION)
也就是说,无法通过简单的宿主机的目录挂载实现ClickHouse数据的持久化。
解决方案
核心思想 ClickHouse data → Docker Volume → WSL2 ext4 。Docker 用于存储数据的 docker-desktop-data(WSL2)` 整个发行版放在 D 盘。首先查看一下当前的wsl发行版实例有哪些:
bash
C:\Users\billy>wsl -l -v
NAME STATE VERSION
* docker-desktop Stopped 2
docker-desktop-data Stopped 2
ubuntu2204_1
docker-desktop
(1)Docker引擎本体,运行dockerd、containerd、网络、cgroup,本质上是Docker的"操作系统"。
(2)由Docker-Desktop自动创建、管理,不要登录、修改!
docker-desktop-data
(1)Docker的"硬盘/数据盘",存放了Docker volumes、容器的writable layer、镜像层数据。
(2)是一个ext4.vhdx,当Docker-Desktop安装后,默认在C盘。
具体操作过程:
- 停止
Docker Desktop和WSL2
bash
wsl --shutdown
- 导出用于存储Docker数据的
WSL2发行版docker-desktop-data
bash
wsl --export docker-desktop-data D:\wsl\docker-desktop-data.tar
- 注销原来的发行版
bash
wsl --unregister docker-desktop-data
- 在
D盘重新导入
bash
wsl --import docker-desktop-data D:\wsl\docker-desktop-data D:\wsl\docker-desktop-data.tar --version 2
- 启动
Docker Desktop - 使用 Docker Volume`替换原本的目录挂载
yaml
services:
clickhouse:
volumes:
# 数据目录通过volume卷映射
- clickhouse_data:/var/lib/clickhouse
# 定义volume
volumes:
clickhouse_data:
这样数据会存储在docker的内部Linux文件系统中(即在d盘的docker-desktop-data这个WSL2发行版中)
随着Docker-Desktop版本的升级,以4.48.0版本为例,使用wsl -l -v命令你会发现docker-deskto-data这项WSL发行版实例没有了。原因是Docker-Desktop对其进行了升级,可以通过设置项 → Resources → Advanced选择Disk Image location(磁盘镜像位置),此配置会决定数据存储位置。
点击Browse选择指定磁盘、目录后,数据会自动进行迁移,相比上面的发行版迁移更加简便。

WSL2调优,贴近生产模式
在Windows上使用Docker,不论从性能、资源使用上都不是最优解(相对于Linux环境),默认安装好的WSL2,其对资源是"能吃就吃",容器则是"能用则用",因此会看到控制台中有关WSL的内存占用飙升。因此需要从WSL2 → Docker-Desktop →容器(ClickHouse)三个层面进行配置优化,使更贴近生产环境。解决思路: 上游限死,下游按比例给 。
WSL2,设置 WSL2 全局内存 / CPU 上限,操作步骤:
- 在 Windows 用户目录 新建/修改
C:\Users\billy\.wslconfig - 关闭Docker、WSL2
wsl --shutdown - 重启生效
针对开发环境(开发机)的建议配置:
nginx
[wsl2]
memory=4GB # 给 WSL2 的硬上限
processors=4 # CPU 核心数(按你实际 CPU 调)
swap=8GB # 防止 OOM
swapFile=D:\\wsl\\wsl-swap.vhdx
关键参数:
memory:WSL2 可使用的最大物理内存上限- 不配置时(默认行为):WSL2按需增长,用多少就拿多少,使用后也不会主动还给Windows
- 配置后:如设为16GB,WSL2最多只能用16GB,超过后会触发
Linux reclaim、swap,极端情况会出现OOM - 典型表现:比如VmmemWSL一路涨到30G+,即使ClickHouse容器空闲了,也没有释放
processors:WSL2 可见的最大 CPU 核心数- 不配置时(默认行为):WSL2会看到全部CPU,ClickHouse会开启大量线程,merge/insert时并行拉满
- 配置后:WSL2 里
nproc= 16,ClickHousesystem.settings.max_threads受影响,同时Windows 桌面不会被卡死 - 典型表现:给太高,
merge时会抢CPU;给合理,吞吐稳定
swap:WSL2 的交换空间大小(Linux swap)- 不配置时(默认行为):大小不好固定、位置不可控、不好观察
- 配置后:当内存不足时,内核会把冷数据 swap 出去;防止ClickHouse merge OOM,容器被直接 kill。
- 典型表现:无swap,merge直接OOM;有swap,merge慢,但不会挂掉
swapFile:指定 swap 文件存放位置- 不配置时(默认行为): 默认存在
C:\Users\xxx\AppData\Local\Temp,C 盘空间会逐步被占用
- 不配置时(默认行为): 默认存在