Docker 环境下 MySQL 数据恢复与导出

如果容器崩溃或删除,数据会不会丢失?

其实只要你在部署时通过 挂载宿主机目录 的方式保存数据,就可以避免这一问题。比如:

docker run -d \
  --name mysql \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -v /opt/docker/mysql/data:/var/lib/mysql \		
  # 容器卷挂载(将宿主机的/opt/docker/mysql/data挂载到容器里的/var/lib/mysql)
  -v /opt/docker/mysql/conf:/etc/mysql/conf.d \ 
  # 容器卷挂载(将宿主机的/opt/docker/mysql/conf挂载到容器里的/etc/mysql/conf.d)
  --restart unless-stopped \
  mysql:8.0

注意可以通过 docker inspect 查看 Mounts ,以获取挂载信息
从中可以看到 docker

  • 将宿主机的 /opt/docker/mysql/data 作为源(source),
  • 容器内目录作为目标(destination

所以说:

  1. 宿主机的目录是「源头」,容器内的目录是「挂载点 / 目标位置」
  2. 宿主机目录有变更时,会同步到容器内的目标目录
  3. 容器内对目标目录的修改,也会实时反映到宿主机的源目录

这样也可以解释:在保留宿主机目录/opt/docker/mysql/data的情况下,重新run一个容器,将容器卷挂载配置好后,容器继承数据的行为

  • 你的 MySQL 数据被挂载到了宿主机的

    /opt/docker/mysql/data
    
  • 即使容器崩溃或删除,数据依然会保存在宿主机上。

使用docker inspect快速查看挂载位置:

docker inspect -f '{{ range .Mounts }}{{ .Source }} -> {{ .Destination }}{{"\n"}}{{ end }}' mysql

输出类似:
在这里插入图片描述


一、MySQL容器删除后的数据恢复方法

当容器被删除后,只要挂载目录还在,就能恢复数据。

# 删除旧容器(如果存在)
docker rm -f mysql

# 重新创建容器并挂载原有数据目录
docker run -d \
  --name mysql \
  -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=你的密码 \
  -v /opt/docker/mysql/data:/var/lib/mysql \  # 关键:挂载原有数据目录
  mysql:你的版本号

注释:-v 参数将宿主机目录 /opt/docker/mysql/data 挂载到容器内 /var/lib/mysql,这是 MySQL 默认的数据存储路径。

  • 原理
    新容器启动后,直接使用挂载目录中的已有数据文件,因此数据库数据会自动恢复。

数据导出方法

在 Docker MySQL 环境下,常见的备份方式有两种:

方法 特点 适用场景
mysqldump 导出 逻辑备份,生成 .sql 文件,更可靠 需要跨版本迁移、单表/全库导出
直接打包数据目录 物理备份,速度快 恢复到相同版本 MySQL

1. 使用 mysqldump 工具(推荐)

# 进入运行中的容器
docker exec -it mysql bash

# 在容器内执行导出命令(导出所有数据库)
mysqldump -u root -p --all-databases > /var/lib/mysql/all_databases.sql

# 输入密码后等待导出完成,退出容器
exit

# 将导出的 SQL 文件复制到宿主机(可选)
cp /opt/docker/mysql/data/all_databases.sql /你的备份目录/

注释:mysqldump 属于逻辑备份,生成的 SQL 文件可读性强,恢复时直接 mysql < 文件.sql 即可。


2. 直接打包数据目录(物理备份)

# 确保容器已停止(避免文件写入冲突)
docker stop mysql

# 打包整个数据目录
tar -czvf /你的备份目录/mysql_data_backup.tar.gz /opt/docker/mysql/data

# 重新启动容器
docker start mysql

注释:物理备份速度快,但要求恢复时 MySQL 版本保持一致,否则可能因数据文件格式不同而出错。


注意事项

  1. 权限问题
    有时宿主机目录的属主不是 MySQL 容器用户(ID=999),需要手动修改:

    sudo chown -R 999:999 /opt/docker/mysql/data
    

    注释:999:999 是 MySQL 容器内默认 mysql 用户的 UID/GID。

  2. 版本兼容性

    • MySQL 数据文件在不同版本间可能不兼容。
    • 如果采用物理备份,新容器的 MySQL 版本必须与旧容器一致
  3. 定期自动备份
    推荐使用 crontab 定时导出:

    # 每天凌晨3点自动导出
    0 3 * * * docker exec mysql mysqldump -u root -p'你的密码' --all-databases > /opt/docker/mysql/backup/$(date +\%Y\%m\%d).sql
    

    注释:这种方法属于逻辑备份,便于跨环境迁移。


二、Redis 的持久化与备份

Redis 默认数据目录是 /data
如果你挂载时这样写:

docker run -d \
  --name redis \
  -p 6379:6379 \
  -v /opt/docker/redis/data:/data \
  redis:7

1. 确认挂载

docker inspect -f '{{ range .Mounts }}{{ .Source }} -> {{ .Destination }}{{"\n"}}{{ end }}' redis

输出:

/opt/docker/redis/data -> /data

2. 数据导出

Redis 持久化依赖 RDB 快照AOF 文件
只要打包 /opt/docker/redis/data 目录即可:

docker stop redis
tar -czvf /backup/redis_data_$(date +%F).tar.gz /opt/docker/redis/data
docker start redis

注释:

  • 如果配置了 appendonly yes,目录里会有 appendonly.aof 文件;
  • 如果配置了快照,目录里会有 dump.rdb 文件;
  • 直接备份目录即可。

三、PostgreSQL (pgsql) 的持久化与备份

PostgreSQL 默认数据目录是 /var/lib/postgresql/data

docker run -d \
  --name pgsql \
  -p 5432:5432 \
  -e POSTGRES_PASSWORD=你的密码 \
  -v /opt/docker/pgsql/data:/var/lib/postgresql/data \
  postgres:15

1. 确认挂载

docker inspect -f '{{ range .Mounts }}{{ .Source }} -> {{ .Destination }}{{"\n"}}{{ end }}' pgsql

输出:

/opt/docker/pgsql/data -> /var/lib/postgresql/data

2. 导出数据

逻辑备份(推荐)

docker exec pgsql pg_dumpall -U postgres > /opt/docker/pgsql/backup/all.sql

物理备份(打包目录)

docker stop pgsql
tar -czvf /backup/pgsql_data_$(date +%F).tar.gz /opt/docker/pgsql/data
docker start pgsql

四、常见数据库容器挂载路径对照表

数据库 容器内默认数据目录 宿主机常见挂载示例
MySQL /var/lib/mysql /opt/docker/mysql/data
Redis /data /opt/docker/redis/data
PostgreSQL /var/lib/postgresql/data /opt/docker/pgsql/data
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐