mysql-bind-mount-to-named-volume-migration

Docker Compose:MySQL 从绑定目录改为命名卷后「数据不见了」?迁移与选型说明

适用场景:原先使用 ./data/mysql:/var/lib/mysql 持久化,后来改为 mysql-data:/var/lib/mysql命名卷,发现库里没有以前的库表。本文说明原因,并给出两种通用解决方案(迁移进卷 / 改回绑定目录),可直接用于团队文档或技术博文。


一、现象

  • 修改 docker-compose.yml 后,MySQL 能正常启动。
  • 但登录后发现:以前的数据库、表都不见了,像刚装好的新实例。
  • 宿主机上 ./data/mysql(或你原来的目录)里明明还有一堆文件

二、原因(核心一句话)

绑定挂载(bind mount)和命名卷(named volume)是两套不同的存储位置。

改配置后,新容器读写的是新位置 (例如空的 mysql-data 卷),不会自动 去用你旧的 ./data/mysql,所以旧数据「看起来丢了」,其实仍在原目录里。

挂载方式 数据实际在哪
./data/mysql:/var/lib/mysql 宿主机你指定的目录(如项目下 data/mysql
mysql-data:/var/lib/mysql Docker 管理的卷(docker volume ls 里能看到,路径由 Docker 决定)

MySQL 官方镜像只在数据目录为空 时执行 docker-entrypoint-initdb.d 里的初始化脚本;若命名卷是新的空卷,还会再跑一遍初始化,进一步让你感觉「全是新的」。


三、方案 A:把旧数据迁移进命名卷(推荐继续用命名卷时)

目标 :保留 mysql-data:/var/lib/mysql 的配置,把原 ./data/mysql 里的内容拷进该卷。

前置条件

  • MySQL 已停止(避免拷贝过程中文件被写坏)。
  • 旧数据与当前镜像 MySQL 大版本一致(例如都是 8.0),跨大版本直接拷数据目录风险高,应用备份/逻辑导出迁移。
  • 若命名卷里已经跑过一次 MySQL、生成了新数据,且你要以旧数据为准,通常需要先处理空卷(见下)。

操作步骤(Linux / macOS / Git Bash)

在项目根目录(docker-compose.yml 所在目录)执行:

bash 复制代码
# 1. 停止 MySQL
docker compose stop mysql

# 2. 查看卷名(Compose 会加项目前缀,常见为 目录名_mysql-data)
docker volume ls

# 3. 若确定要用旧数据完全覆盖卷内内容,且卷可删(注意:会删掉卷里当前所有内容)
# docker volume rm <项目前缀>_mysql-data
# 若删不掉,先:docker compose rm -f mysql

# 4. 将宿主机旧数据目录拷入命名卷(把 VOLUME_NAME 换成上一步看到的全名)
docker run --rm \
  -v VOLUME_NAME:/to \
  -v "$(pwd)/data/mysql:/from:ro" \
  alpine sh -c "cp -a /from/. /to/"

# 5. 启动 MySQL
docker compose up -d mysql

Windows PowerShell(Docker Desktop)

项目根目录 执行,VOLUME_NAME 替换为 docker volume ls 中的实际名称(例如 devops-core_mysql-data):

powershell 复制代码
docker compose stop mysql

docker volume ls

docker run --rm `
  -v "VOLUME_NAME:/to" `
  -v "${PWD}/data/mysql:/from:ro" `
  alpine sh -c "cp -a /from/. /to/"

docker compose up -d mysql

验证

bash 复制代码
docker compose exec mysql mysql -u root -p -e "SHOW DATABASES;"

应能看到迁移前的库名。

注意事项

  • 拷贝前尽量保证旧库是正常关闭后的数据目录;异常宕机后的目录可能需要 InnoDB 恢复,以日志为准。
  • 不要把不同机器、不同小版本混用 不经测试;生产环境更建议:mysqldump 逻辑备份 → 新实例导入

四、方案 B:改回绑定目录(零迁移,立刻用回旧数据)

目标 :不再使用命名卷,继续用 ./data/mysql:/var/lib/mysql

docker-compose.yml 中把:

yaml 复制代码
volumes:
  - mysql-data:/var/lib/mysql

改回:

yaml 复制代码
volumes:
  - ./data/mysql:/var/lib/mysql

并在文件底部 volumes: 声明块 里删除不再使用的 mysql-data:(若没有其他服务引用)。

然后:

bash 复制代码
docker compose up -d mysql

数据会立刻从原 ./data/mysql 读取,无需拷贝

注意 :之后请始终在同一项目根目录 执行 docker compose,避免相对路径 ./data/mysql 指向别的位置。


五、选型建议(方便写进团队规范)

需求 更合适的做法
数据要跟项目目录放一起、方便备份/拷贝 绑定挂载 ./data/mysql
避免「换目录执行 compose 导致换了一套数据」、与平台无关 命名卷 mysql-data
已用命名卷但历史数据在旧目录 方案 A 迁移,或方案 B改回

六、一句话总结

改挂载 = 换磁盘;旧数据不会自动跟过去。

要么把旧目录拷进新卷 (方案 A),要么继续挂载旧目录(方案 B)。


版权声明与转载

本文为通用运维说明,可根据需要修改示例路径、卷名后用于内部 Wiki 或公开技术博客;转载时注明出处即可。

相关推荐
数据库幼崽3 小时前
ProxySQL官方文档之Audit Log
mysql
liqianpin13 小时前
SpringBoot集成Flink-CDC,实现对数据库数据的监听
数据库·spring boot·flink
数据库幼崽3 小时前
Proxy SQL验证方式
数据库·mysql
wregjru3 小时前
【mysql】1.库的操作
数据库
feng68_3 小时前
MySQL-Router+MySQL-MGR
android·linux·运维·数据库·mysql·adb
黄焖鸡能干四碗3 小时前
企业数据架构、应用架构、技术架构设计方案(PPT文件)
大数据·运维·数据库·安全·架构·需求分析
不会写DN3 小时前
php 如何使用mysqli连接mysql
开发语言·mysql·php
王仲肖3 小时前
PostgreSQL 索引内部机制与表重建深度解析
数据库·postgresql
摇滚侠3 小时前
Redis 怎么用,Java 开发,Redis 怎么用
java·数据库·redis