数据备份与恢复 #
数据备份概述 #
为什么需要备份? #
text
┌─────────────────────────────────────────────────────┐
│ 数据备份的重要性 │
├─────────────────────────────────────────────────────┤
│ │
│ 1. 防止数据丢失 │
│ 2. 灾难恢复 │
│ 3. 数据迁移 │
│ 4. 版本回滚 │
│ 5. 合规要求 │
│ │
└─────────────────────────────────────────────────────┘
备份类型 #
| 类型 | 说明 | 频率 |
|---|---|---|
| 全量备份 | 备份所有数据 | 每周 |
| 增量备份 | 备份变化的数据 | 每天 |
| 差异备份 | 备份与上次全量备份的差异 | 每天 |
数据卷备份 #
备份单个数据卷 #
bash
# 使用临时容器备份数据卷
docker run --rm \
-v myvolume:/source:ro \
-v $(pwd)/backup:/backup \
alpine tar czf /backup/myvolume-$(date +%Y%m%d).tar.gz -C /source .
# 备份到标准输出
docker run --rm \
-v myvolume:/source:ro \
alpine tar czf - -C /source . > myvolume-backup.tar.gz
# 使用压缩
docker run --rm \
-v myvolume:/source:ro \
-v $(pwd)/backup:/backup \
alpine tar cjf /backup/myvolume.tar.bz2 -C /source .
备份多个数据卷 #
bash
#!/bin/bash
# backup-volumes.sh
BACKUP_DIR="/backup/volumes"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
for volume in $(docker volume ls -q); do
echo "Backing up volume: $volume"
docker run --rm \
-v $volume:/source:ro \
-v $BACKUP_DIR:/backup \
alpine tar czf /backup/${volume}-${DATE}.tar.gz -C /source .
done
echo "Backup completed!"
备份容器数据 #
bash
# 备份运行中容器的数据
docker run --rm \
--volumes-from mycontainer \
-v $(pwd)/backup:/backup \
alpine tar czf /backup/container-data.tar.gz /app/data
# 备份特定目录
docker run --rm \
--volumes-from mycontainer \
-v $(pwd)/backup:/backup \
alpine tar czf /backup/mysql-data.tar.gz /var/lib/mysql
数据恢复 #
恢复数据卷 #
bash
# 创建新数据卷
docker volume create restored-volume
# 恢复数据
docker run --rm \
-v restored-volume:/target \
-v $(pwd)/backup:/backup \
alpine sh -c "cd /target && tar xzf /backup/myvolume-backup.tar.gz"
# 恢复到现有数据卷(会覆盖)
docker run --rm \
-v myvolume:/target \
-v $(pwd)/backup:/backup \
alpine sh -c "cd /target && tar xzf /backup/myvolume-backup.tar.gz"
从标准输入恢复 #
bash
# 从标准输入恢复
cat myvolume-backup.tar.gz | docker run --rm -i \
-v myvolume:/target \
alpine sh -c "cd /target && tar xzf -"
恢复到容器 #
bash
# 恢复数据到运行中的容器
docker run --rm \
--volumes-from mycontainer \
-v $(pwd)/backup:/backup \
alpine tar xzf /backup/container-data.tar.gz -C /
数据库备份 #
MySQL备份 #
bash
# 使用mysqldump备份
docker exec my-mysql mysqldump -u root -proot --all-databases > mysql-backup.sql
# 备份特定数据库
docker exec my-mysql mysqldump -u root -proot mydb > mydb-backup.sql
# 使用压缩
docker exec my-mysql mysqldump -u root -proot --all-databases | gzip > mysql-backup.sql.gz
# 恢复MySQL
cat mysql-backup.sql | docker exec -i my-mysql mysql -u root -proot
# 恢复压缩备份
gunzip < mysql-backup.sql.gz | docker exec -i my-mysql mysql -u root -proot
PostgreSQL备份 #
bash
# 使用pg_dump备份
docker exec my-postgres pg_dump -U postgres mydb > postgres-backup.sql
# 备份所有数据库
docker exec my-postgres pg_dumpall -U postgres > postgres-all-backup.sql
# 使用压缩
docker exec my-postgres pg_dump -U postgres mydb | gzip > postgres-backup.sql.gz
# 恢复PostgreSQL
cat postgres-backup.sql | docker exec -i my-postgres psql -U postgres
# 恢复压缩备份
gunzip < postgres-backup.sql.gz | docker exec -i my-postgres psql -U postgres
MongoDB备份 #
bash
# 使用mongodump备份
docker exec my-mongo mongodump --archive > mongo-backup.archive
# 备份特定数据库
docker exec my-mongo mongodump --db mydb --archive > mydb-backup.archive
# 使用压缩
docker exec my-mongo mongodump --archive | gzip > mongo-backup.archive.gz
# 恢复MongoDB
cat mongo-backup.archive | docker exec -i my-mongo mongorestore --archive
# 恢复压缩备份
gunzip < mongo-backup.archive.gz | docker exec -i my-mongo mongorestore --archive
Redis备份 #
bash
# 触发RDB快照
docker exec my-redis redis-cli BGSAVE
# 复制RDB文件
docker cp my-redis:/data/dump.rdb ./redis-backup-$(date +%Y%m%d).rdb
# 恢复Redis
docker cp ./redis-backup.rdb my-redis:/data/dump.rdb
docker restart my-redis
自动化备份 #
定时备份脚本 #
bash
#!/bin/bash
# auto-backup.sh
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30
# 创建备份目录
mkdir -p $BACKUP_DIR
# 备份数据卷
echo "Backing up volumes..."
for volume in $(docker volume ls -q); do
docker run --rm \
-v $volume:/source:ro \
-v $BACKUP_DIR:/backup \
alpine tar czf /backup/${volume}-${DATE}.tar.gz -C /source .
done
# 备份MySQL
echo "Backing up MySQL..."
docker exec my-mysql mysqldump -u root -proot --all-databases | gzip > $BACKUP_DIR/mysql-${DATE}.sql.gz
# 备份PostgreSQL
echo "Backing up PostgreSQL..."
docker exec my-postgres pg_dumpall -U postgres | gzip > $BACKUP_DIR/postgres-${DATE}.sql.gz
# 清理旧备份
echo "Cleaning old backups..."
find $BACKUP_DIR -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed at $(date)"
Cron定时任务 #
bash
# 编辑crontab
crontab -e
# 每天凌晨2点执行备份
0 2 * * * /path/to/auto-backup.sh >> /var/log/docker-backup.log 2>&1
# 每周日凌晨3点执行全量备份
0 3 * * 0 /path/to/full-backup.sh >> /var/log/docker-backup.log 2>&1
# 每小时执行增量备份
0 * * * * /path/to/incremental-backup.sh >> /var/log/docker-backup.log 2>&1
远程备份 #
备份到S3 #
bash
#!/bin/bash
# backup-to-s3.sh
BACKUP_DIR="/tmp/backup"
S3_BUCKET="s3://my-backup-bucket/docker"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
# 备份数据卷
for volume in $(docker volume ls -q); do
docker run --rm \
-v $volume:/source:ro \
-v $BACKUP_DIR:/backup \
alpine tar czf /backup/${volume}-${DATE}.tar.gz -C /source .
done
# 上传到S3
aws s3 sync $BACKUP_DIR $S3_BUCKET/$DATE/
# 清理本地备份
rm -rf $BACKUP_DIR
echo "Backup uploaded to S3: $S3_BUCKET/$DATE/"
备份到远程服务器 #
bash
#!/bin/bash
# backup-to-remote.sh
REMOTE_HOST="backup.example.com"
REMOTE_DIR="/backup/docker"
DATE=$(date +%Y%m%d_%H%M%S)
# 备份并传输
docker run --rm \
-v myvolume:/source:ro \
alpine tar czf - -C /source . | \
ssh $REMOTE_HOST "cat > $REMOTE_DIR/myvolume-${DATE}.tar.gz"
# 或使用rsync
docker run --rm \
-v myvolume:/source:ro \
-v $(pwd):/backup \
alpine tar czf /backup/myvolume-${DATE}.tar.gz -C /source .
rsync -avz $(pwd)/myvolume-${DATE}.tar.gz $REMOTE_HOST:$REMOTE_DIR/
数据迁移 #
迁移数据卷 #
bash
# 源主机: 导出数据卷
docker run --rm \
-v source-volume:/source:ro \
-v $(pwd):/backup \
alpine tar czf /backup/volume.tar.gz -C /source .
# 传输文件到目标主机
scp volume.tar.gz target-host:/tmp/
# 目标主机: 导入数据卷
docker volume create target-volume
docker run --rm \
-v target-volume:/target \
-v /tmp:/backup \
alpine tar xzf /backup/volume.tar.gz -C /target
迁移容器 #
bash
# 导出容器
docker export mycontainer > container.tar
# 传输并导入
scp container.tar target-host:/tmp/
docker import /tmp/container.tar myimage:v1.0
# 运行新容器
docker run -d --name new-container myimage:v1.0
迁移整个Docker环境 #
bash
#!/bin/bash
# migrate-docker.sh
# 导出所有镜像
docker save $(docker images -q) -o all-images.tar
# 导出所有数据卷
for volume in $(docker volume ls -q); do
docker run --rm \
-v $volume:/source:ro \
-v $(pwd):/backup \
alpine tar czf /backup/${volume}.tar.gz -C /source .
done
# 导出容器配置
for container in $(docker ps -aq); do
docker inspect $container > ${container}.json
done
# 打包传输
tar czf docker-migration.tar.gz *.tar *.json
备份验证 #
验证备份完整性 #
bash
#!/bin/bash
# verify-backup.sh
BACKUP_FILE=$1
# 验证tar文件
if tar tzf $BACKUP_FILE > /dev/null 2>&1; then
echo "Backup is valid: $BACKUP_FILE"
exit 0
else
echo "Backup is corrupted: $BACKUP_FILE"
exit 1
fi
测试恢复 #
bash
#!/bin/bash
# test-restore.sh
BACKUP_FILE=$1
TEST_VOLUME="test-restore-$(date +%s)"
# 创建测试卷
docker volume create $TEST_VOLUME
# 恢复数据
docker run --rm \
-v $TEST_VOLUME:/target \
-v $(pwd):/backup \
alpine tar xzf /backup/$BACKUP_FILE -C /target
# 验证数据
docker run --rm \
-v $TEST_VOLUME:/data \
alpine ls -la /data
# 清理
docker volume rm $TEST_VOLUME
小结 #
本节学习了Docker数据的备份和恢复:
- 数据卷备份方法
- 数据恢复操作
- 数据库备份策略
- 自动化备份配置
- 远程备份方案
- 数据迁移方法
下一步 #
接下来,让我们学习 网络基础,了解Docker网络的基本概念。