我有一个 mysql 实例在 docker 容器中运行。我在
/var/lib/mysql
中安装了一个卷,以在关闭容器后保留数据。我认为我有两种选择将数据库备份到主机系统:
docker run --rm --volumes-from db -v {BACKUP_PATH_ON_HOST_SYSTEM}:/backup ubuntu tar cvf /backup/backup.tar /var/lib/mysql
基本上运行上面的命令,但我没有备份卷,而是创建了一个mysqldump,我将其复制到
/backup
。
哪个选项更好?
我也有类似的需求。就我而言,我故意使用旧的
mysql
Docker 镜像,如下所示:
db:
image: mysql:5.6
container_name: ${COMPOSE_SITE_NAME}_mysql
volumes:
- db_files:/var/lib/mysql
# Load the initial SQL dump into the DB when it is created.
# This only runs once if the DB is empty.
- ${SQL_DUMP_FILE}:/docker-entrypoint-initdb.d/dump.sql
environment:
MYSQL_ROOT_PASSWORD: ${WORDPRESS_DB_PASS}
...
volumes:
db_files:
name: ${COMPOSE_SITE_NAME}_db_files
如果卷丢失,可以使用转储文件重新创建它。就我而言,我更喜欢创建转储文件,而不是在该
/var/lib/mysql
文件夹中保留 SQL 文件的杂音。
docker-compose exec db sh -c '\
mysqldump -uroot -p$MYSQL_ROOT_PASSWORD --all-databases --routines --triggers \
' | gzip -c > /path/outside/docker/backup-`date '+%Y-%m-%d'`.sql.gz
由于 stdout 重定向 (
>
),这将在 Docker 外部的主机上创建一个压缩转储文件。我使用 sh -c ''
,这样我就可以在容器中重用 MYSQL_ROOT_PASSWORD
环境变量。请随意调整它以满足您的 MySQL 要求,例如指定受限用户。
使用默认标志,转储文件将包含
DROP TABLE IF EXISTS
语句,以便您可以替换现有数据库而不删除卷(docker-compose down
,然后 docker volume rm ...
)。
我强烈建议不要放弃基于SQL的备份,转而使用docker卷备份(用于数据库数据)!
虽然这样做可能很诱人(易于设置和自动化),但您应该记住,它并不能保证您将检索数据。 Docker 卷转储不仅包含数据,还包含其结构(并非所有平台都通用)。
我可以举一个它可能不起作用的例子,那就是当您想在不同的磁盘上使用 docker 卷转储时。举例来说:
M-1
,卷位于持久存储(磁盘)上 D-1
M-2
上使用磁盘 D-2
设置另一台容器化服务器(假设该服务器的空间比 D-1
D-2
您使用的块大小与D-1
D-1
上的卷转储到 .tar,并希望将其加载到 D-2
上的卷(例如从生产到开发)M-2
上运行服务器并期望它能够正常工作很可能不会。此外,错误消息可能会产生误导并且调试起来很痛苦。最糟糕的是,有时它可能有效,有时则无效(在这种情况下取决于磁盘格式化)。
查看官方 MySQL 文档,他们建议使用
mysqldump
用于 docker 化服务器的方法(忽略它们是不明智的)。
我也有类似的问题。带有 mysql 的 WordPress 容器。我目前正在备份 mysql 的持久卷,并使用这些副本来启动重复的 WordPress 环境(例如,从开发环境到 live env)。但有时副本会丢失小块数据,例如颜色代码错误或字体图标丢失。 docker 容器似乎正在 Ram 中缓存一些数据,当从卷(磁盘上)获取备份时,并非所有数据都会成功。所以我认为转储 sql dB 或至少关闭 sql 容器是必要的。还有其他想法吗?