如何在docker-compose down前自动执行MySQL数据库备份?
当然可以实现这种「down前钩子」的需求,你已经写了核心逻辑的脚本,接下来解决动态获取容器名的问题就很简单了,我给你几个实用的方案:
方案1:直接用docker-compose服务名(最推荐)
其实根本不需要硬编码容器名——docker-compose本身就支持通过服务名直接执行命令,不管容器实际叫什么(比如自动加的项目前缀)。假设你的docker-compose.yml里MySQL服务的名称是mysql(比如下面这样的配置):
services: mysql: image: mysql:8.0 # 其他配置...
那你可以把脚本改成这样,直接用服务名替代固定容器名:
#!/bin/bash CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # 用docker-compose exec + 服务名,无需硬编码容器名,-T避免终端交互问题 docker-compose exec -T mysql sh -c 'exec mysqldump --databases local -uroot -p"$MYSQL_ROOT_PASSWORD"' > "$CURRENT_DIR/docker/data/backup/local.sql" # 可选:检查备份是否成功,再执行down if [ $? -eq 0 ]; then echo "备份完成,正在停止服务..." docker-compose down else echo "备份失败,取消停止服务操作" exit 1 fi
这个方案最省心,因为服务名是你自己在docker-compose.yml里定义的,不会随便变,而且docker-compose会自动找到对应的容器。
方案2:从docker-compose.yml动态提取服务名(更灵活)
如果你的MySQL服务名不是固定的mysql,或者想从配置文件自动读取,可以用yq(一款专门处理YAML的命令行工具)来提取服务名。
首先安装yq(不同系统安装方式不同,比如Ubuntu用apt install yq,macOS用brew install yq),然后修改脚本:
#!/bin/bash CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # 从docker-compose.yml中提取包含"mysql"的服务名(适配类似db-mysql的命名) MYSQL_SERVICE=$(yq e '.services | keys | .[] | select(. | test("mysql"))' "$CURRENT_DIR/docker-compose.yml") docker-compose exec -T "$MYSQL_SERVICE" sh -c 'exec mysqldump --databases local -uroot -p"$MYSQL_ROOT_PASSWORD"' > "$CURRENT_DIR/docker/data/backup/local.sql" docker-compose down
这个方案适合服务名可能变化的场景,自动匹配符合条件的服务。
方案3:通过docker-compose ps获取容器名
另一种思路是用docker-compose ps命令动态获取MySQL服务对应的容器名:
#!/bin/bash CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # 获取mysql服务对应的容器ID/名称(-q参数只输出容器标识) MYSQL_CONTAINER=$(docker-compose ps -q mysql) docker exec "$MYSQL_CONTAINER" sh -c 'exec mysqldump --databases local -uroot -p"$MYSQL_ROOT_PASSWORD"' > "$CURRENT_DIR/docker/data/backup/local.sql" docker-compose down
这个方法直接从运行中的容器列表里获取,适合需要容器名而非服务名的场景。
额外小贴士
- 记得给
down.sh添加执行权限:chmod +x down.sh,之后每次用./down.sh替代docker-compose down即可 - 如果备份的数据库很大,建议加上
--single-transaction参数(InnoDB引擎),避免锁表:mysqldump --single-transaction --databases local ... - 可以把备份文件按时间命名,避免覆盖:
"$CURRENT_DIR/docker/data/backup/local_$(date +%Y%m%d_%H%M%S).sql"
内容的提问来源于stack exchange,提问作者RomkaLTU
相关产品推荐
相关产品推荐

