docker mysql迁移核心是复用数据卷+重建容器配置,秒级恢复需路径、权限、版本三者对齐;绑定挂载直接打包宿主目录,命名卷须用临时容器导出;物理恢复快但要求严格,逻辑恢复兼容跨版本。

docker 挂载迁移不是“复制容器”,而是复用数据卷 + 重建容器配置。只要宿主机上存有原始挂载目录(或命名卷),就能跳过 mysqldump 导入,实现秒级恢复——但前提是路径、权限、MySQL 版本三者对齐。
确认挂载方式:绑定挂载 vs 命名卷
迁移前必须分清你用的是哪种挂载,操作路径完全不同:
- 绑定挂载(
-v /host/path:/var/lib/mysql):数据在宿主机真实路径下,直接打包该目录即可,如/opt/mysql/data - 命名卷(
-v mysql-data:/var/lib/mysql):需用临时容器导出,不能直接cp宿主机文件;执行:docker run --rm -v mysql-data:/volume -v $(pwd):/backup alpine tar czf /backup/mysql-data.tar.gz -C /volume . - 没挂载?那数据就在容器内部,
docker commit或docker export都救不回——此时只能靠mysqldump,别试物理拷贝
停机状态下物理恢复:绕过 SQL 解析的最快路径
适用于同版本 MySQL(如都是 mysql:8.0.33)、且能接受短暂停机的场景。速度比 mysqldump 快 5–10 倍,但容错率低。
- 先停旧容器:
docker stop mysql-old - 把备份的
mysql-data.tar.gz解压到新宿主机的挂载路径(如/opt/mysql/data),确保目录为空 - 启动新容器时,
-v必须指向同一路径,且加--user 999:999(MySQL 官方镜像默认 uid/gid 是 999) - 关键检查项:
ls -l /opt/mysql/data确认所有文件属主是999:999;否则进容器执行chown -R 999:999 /var/lib/mysql
mysqldump 导入失败的常见卡点
很多人用 docker exec -i mysql-new mysql -uroot -p123456 报错退出,其实问题不在命令本身,而在环境细节:
-
backup.sql文件编码必须是 UTF-8 无 BOM,含中文时尤其容易因编码错乱导致ERROR 1064 - 若 dump 文件里没
CREATE DATABASE,而你又没手动建库,会报ERROR 1049 (42000): Unknown database - MySQL 8.0+ 默认禁用
local_infile,如果 dump 里有LOAD DATA INFILE,需启动容器时加参数:--secure-file-priv="" - 更稳妥的做法是进容器执行:
mysql -uroot -p123456 -e "source /backups/backup.sql"(前提是已-v挂载了备份目录)
字符集与配置文件必须手动核对
即使数据成功导入,应用连上去发现中文变问号、时间错乱、排序异常——大概率是配置没同步:
- 检查新容器是否挂载了原
my.cnf:docker inspect mysql-new | grep -A5 Mounts,确认/etc/mysql/conf.d/被映射 - 重点比对三项:
character-set-server=utf8mb4、collation-server=utf8mb4_0900_ai_ci(MySQL 8.0)、default-time-zone='+08:00' - 若用
docker-compose.yml启动,environment:下的MYSQL_INITDB_SKIP_TZINFO=1可能导致时区失效,建议删掉,改用配置文件指定
mysql:5.7 迁到 mysql:8.0)。真正容易被忽略的,是恢复后没验证 SHOW VARIABLES LIKE 'character_set%'; 和 SELECT NOW(); ——这两个命令一跑,八成问题当场暴露。











