好的,Docker 迁移容器的最佳方法遵循一个核心原则:容器本身是临时的,状态和数据应该持久化,迁移的应该是构建容器的「蓝图」和「数据」。
下面我将详细介绍几种最佳方法,从推荐程度由高到低排列。
这是最标准、最符合 Docker 设计哲学的方法。将容器的状态保存为镜像,推送到镜像仓库,然后在目标机器拉取运行。
# 1. 在源服务器上,将正在运行的容器提交为镜像
# 语法:docker commit <容器名> <镜像名:标签>
docker commit my_app_container my_app:2024-migration
# 2. 给镜像打上远程仓库的标签
docker tag my_app:2024-migration my-registry.com/username/my_app:latest
# 3. 登录 Docker Registry(如 Docker Hub、私有仓库)
docker login my-registry.com
# 4. 推送镜像到仓库
docker push my-registry.com/username/my_app:latest
# 5. 在目标服务器上,拉取镜像
docker pull my-registry.com/username/my_app:latest
# 6. 根据原来的参数重新创建并运行容器
docker run -d \
--name my_app_container \
-p 8080:80 \
-v /host/path:/container/path \
-e "ENV_VAR=value" \
my-registry.com/username/my_app:latest
docker save 和 docker load当没有镜像仓库或网络受限时,可以使用这种方式。
# 1. 在源服务器上,将容器提交为镜像
docker commit my_app_container my_app:latest
# 2. 将镜像保存为 tar 文件
docker save -o my_app_backup.tar my_app:latest
# 3. 压缩文件(可选,节省空间)
gzip my_app_backup.tar
# 4. 传输文件到目标服务器
scp my_app_backup.tar.gz user@target-server:/path/to/backup/
# 5. 在目标服务器上,解压并加载镜像
gunzip my_app_backup.tar.gz
docker load -i my_app_backup.tar
# 6. 重新创建并运行容器
docker run -d \
--name my_app_container \
-p 8080:80 \
-v /host/path:/container/path \
-e "ENV_VAR=value" \
my_app:latest
如果容器是通过 Docker Compose 管理的,迁移整个应用栈的最佳方式是迁移 docker-compose.yml 文件。
# 1. 在源服务器上,确保有 docker-compose.yml 文件
# 示例 docker-compose.yml:
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./data:/usr/share/nginx/html
environment:
- NGINX_HOST=localhost
database:
image: postgres:13
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
# 2. 停止服务(可选,保证数据一致性)
docker-compose down
# 3. 备份数据卷(重要!)
tar -czf app_data_backup.tar.gz ./data
# 4. 传输 docker-compose.yml 和数据备份到目标服务器
scp docker-compose.yml user@target-server:/app/
scp app_data_backup.tar.gz user@target-server:/app/
# 5. 在目标服务器上,恢复数据并启动服务
cd /app
tar -xzf app_data_backup.tar.gz
docker-compose up -d
对于有状态服务(数据库等),数据卷的迁移至关重要。
# 1. 创建数据卷备份
docker run --rm \
-v my_app_data:/volume \
-v $(pwd):/backup \
alpine \
tar -czf /backup/app_data_backup.tar.gz -C /volume ./
# 2. 传输备份文件到目标服务器
scp app_data_backup.tar.gz user@target-server:/backup/
# 3. 在目标服务器上恢复数据卷
# 首先创建数据卷
docker volume create my_app_data
# 然后恢复数据
docker run --rm \
-v my_app_data:/volume \
-v $(pwd):/backup \
alpine \
sh -c "rm -rf /volume/* && tar -xzf /backup/app_data_backup.tar.gz -C /volume"
#!/bin/bash
# migration_script.sh
CONTAINER_NAME="my_app"
BACKUP_TAG="migration-$(date +%Y%m%d)"
BACKUP_FILE="backup_${BACKUP_TAG}.tar.gz"
VOLUME_NAME="app_data"
echo "=== 开始迁移容器: $CONTAINER_NAME ==="
# 1. 停止容器(保证一致性)
echo "1. 停止容器..."
docker stop $CONTAINER_NAME
# 2. 备份数据卷
echo "2. 备份数据卷..."
docker run --rm \
-v $VOLUME_NAME:/volume \
-v $(pwd):/backup \
alpine \
tar -czf /backup/volume_$BACKUP_TAG.tar.gz -C /volume ./
# 3. 提交容器为镜像
echo "3. 提交容器为镜像..."
docker commit $CONTAINER_NAME ${CONTAINER_NAME}:$BACKUP_TAG
# 4. 保存镜像
echo "4. 保存镜像..."
docker save ${CONTAINER_NAME}:$BACKUP_TAG | gzip > $BACKUP_FILE
# 5. 重新启动容器(源服务器)
echo "5. 在源服务器重新启动容器..."
docker start $CONTAINER_NAME
echo "=== 迁移完成!备份文件: $BACKUP_FILE ==="
echo "请将 $BACKUP_FILE 和 volume_$BACKUP_TAG.tar.gz 传输到目标服务器"
| 场景 | 推荐方法 | 关键步骤 |
|---|---|---|
| 生产环境迁移 | Docker Registry | commit → push → pull → run |
| 离线环境迁移 | Save/Load | commit → save → 传输 → load → run |
| 多容器应用 | Docker Compose | 备份 docker-compose.yml + 数据卷 |
| 有状态服务 | 数据卷备份 | 备份数据卷 + 镜像迁移 |
docker inspect 查看原容器的配置记住:容器应该是可丢弃的,重要的数据和配置应该外化,这样迁移才会顺利。