换Compose项目名后数据“不见了”实为挂载错卷,旧卷仍存在但被重命名;需用docker volume ls | grep筛选旧卷名,再通过volumes.name显式指定复用,或检查WSL2内核兼容性修复挂载异常。

换 Compose 项目名后数据“不见了”,大概率不是丢了,而是挂到了另一个卷上——Docker Desktop 按项目名自动重命名了卷,旧卷还在,只是新容器没连过去。
docker volume ls 看不到旧卷?其实是被重命名了
默认情况下,Docker Compose 会把卷名拼成 projectname_servicename_data 这种格式。你改了 COMPOSE_PROJECT_NAME 或用了 -p 参数,它就立刻换一套命名规则,新建的卷和旧卷完全不重叠。
旧卷不会被删,但也不会自动复用。你执行 docker volume ls 时看到的全是新名字,老卷藏在列表里,只是你没认出来。
- 查所有卷:
docker volume ls - 筛出可能的旧卷:
docker volume ls | grep -i "old-project-name"(把old-project-name换成你之前的项目名) - 确认某个卷是否含数据:
docker run --rm -v <volume_name>:/data alpine ls -l /data</volume_name>
怎么让新容器继续用旧卷?改 docker-compose.yml
别删卷、别重建,直接把新配置指向旧卷即可。关键点是:显式声明卷,并指定 name 字段,强制复用。
比如你发现旧卷叫 myapp-db-data,而新配置里写的是 db-data,那就得手动对齐:
services:
db:
image: postgres:15
volumes:
- db-data:/var/lib/postgresql/data
<p>volumes:
db-data:
name: myapp-db-data注意:name 必须完全匹配 docker volume ls 里显示的名字,大小写、连字符都不能错。
- 如果旧卷是匿名卷(名字一长串哈希),
name字段不能用,只能改用external: true并确保name不填,靠source匹配 - 绑定挂载(
./data:/var/lib/postgresql/data)不受项目名影响,但要检查宿主机路径是否存在、权限是否正确
为什么 inspect 卷会显示 Driver: local 但 Mountpoint 是空的?
这不是卷损坏,而是 Docker Desktop 的 WSL2 后端在某些场景下(比如自编译内核后、或升级失败)会“看不见”已存在的卷元数据,导致 Mountpoint 字段为空,但实际数据仍在 /var/lib/docker/volumes/<name>/_data</name> 下。
这时候别信 docker volume inspect 的输出,直接进 WSL 查文件系统:
- 进 WSL 发行版:
wsl -d Ubuntu-22.04(换成你实际发行版名) - 查卷路径:
ls -l /var/lib/docker/volumes/myapp-db-data/_data - 如果目录存在且有文件,说明数据完好,问题纯属挂载层映射失败
这种情况下,只要 docker-compose.yml 正确指向该卷名,重启服务就能恢复访问。
最易忽略的一点:WSL2 内核变更会让卷“隐身”
如果你最近替换过 WSL2 内核(比如自己编译过),哪怕只是改了几个模块开关,也可能导致 Docker Desktop 启动时无法加载卷元数据。现象就是 docker volume ls 显示正常,但 inspect 里 Mountpoint 为空,容器启动后目录为空。
这不是数据丢了,是 Docker Desktop 的 WSL 后端和内核之间通信出了偏差。临时解法是回退到官方内核:curl -L https://github.com/microsoft/WSL2-Linux-Kernel/releases/download/linux-msft-wsl-5.15.153.1/ubuntu22.04 -o wsl2_kernel && wsl --update --rollback,再重启 WSL。
真正修复要检查内核配置里是否禁用了 CONFIG_OVERLAY_FS、CONFIG_VETH 或 CONFIG_NETFILTER_XT_MATCH_ADDRTYPE ——Docker Desktop 依赖这些功能做卷挂载和网络桥接,缺一个都可能导致卷不可见。


















