本文档风哥主要介绍Podman容器备份和恢复进阶,包括备份的概念、备份类型、恢复概念以及容器备份、镜像备份和卷备份等内容。风哥教程参考Podman官方文档Backup and Recovery部分,适合容器管理员和开发人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。
Part01-基础概念与理论知识
1.1 备份概念
备份是指将数据或系统的当前状态保存到其他位置,以便在数据丢失或系统故障时恢复。Podman容器备份是指将容器的配置、数据和状态保存到其他位置,以便在容器故障或数据丢失时恢复。更多视频教程www.fgedu.net.cn
- 数据保护:防止数据丢失和损坏
- 系统恢复:在系统故障时快速恢复
- 灾难恢复:在灾难发生时恢复系统
- 版本控制:保存系统的不同版本
- 合规要求:满足行业和地区的合规要求
1.2 备份类型
Podman容器备份的类型主要包括:
- 完全备份:备份容器的所有数据和配置
- 增量备份:只备份自上次备份以来更改的数据
- 差异备份:只备份自上次完全备份以来更改的数据
- 配置备份:只备份容器的配置信息
- 数据备份:只备份容器的数据
1.3 恢复概念
恢复是指将备份的数据或系统状态还原到原始位置或新位置。Podman容器恢复是指将备份的容器配置、数据和状态还原到原始容器或新容器。
- 完全恢复:将容器恢复到备份时的状态
- 部分恢复:只恢复容器的部分数据或配置
- 迁移恢复:将容器从一个环境迁移到另一个环境
- 灾难恢复:在灾难发生后恢复容器
Part02-生产环境规划与建议
2.1 备份策略
生产环境中Podman的备份策略:
## 备份频率
– 完全备份:每周或每月执行一次
– 增量备份:每天执行一次
– 差异备份:每三天或每周执行一次
– 配置备份:每次配置更改后执行
## 备份存储
– 本地存储:将备份存储在本地磁盘
– 网络存储:将备份存储在网络存储设备
– 云存储:将备份存储在云存储服务
– 异地存储:将备份存储在异地,确保灾难恢复
## 备份保留
– 短期保留:保留最近几天的备份
– 中期保留:保留最近几周的备份
– 长期保留:保留最近几个月或几年的备份
– 归档存储:将重要备份归档存储
## 备份验证
– 定期验证:定期验证备份的完整性和可恢复性
– 测试恢复:定期测试恢复过程,确保恢复正常
– 备份监控:监控备份过程,及时发现和解决备份问题
## 恢复计划
– 灾难恢复计划:制定详细的灾难恢复计划
– 恢复时间目标:设定恢复时间目标(RTO)
– 恢复点目标:设定恢复点目标(RPO)
– 恢复演练:定期进行恢复演练,确保恢复计划的有效性
2.2 备份需求
生产环境中Podman的备份需求:
## 功能需求
– 容器备份:支持容器的备份和恢复
– 镜像备份:支持镜像的备份和恢复
– 卷备份:支持卷的备份和恢复
– 配置备份:支持容器配置的备份和恢复
– 自动化备份:支持自动化备份和恢复
## 性能需求
– 备份速度:备份过程快速,不影响容器运行
– 恢复速度:恢复过程快速,减少停机时间
– 备份开销:备份过程开销小,不影响系统性能
– 存储效率:备份存储高效,减少存储空间占用
## 技术需求
– 备份工具:支持多种备份工具
– 备份格式:支持多种备份格式
– 备份集成:与现有备份系统集成
– 备份监控:提供备份监控功能
## 非功能需求
– 可靠性:备份过程可靠,确保数据安全
– 可维护性:备份配置易于管理和维护
– 可扩展性:备份方案可扩展,适应不同的场景
– 成本效益:备份方案成本合理,效益明显
2.3 备份工具
生产环境中Podman的备份工具:
- Podman内置命令:podman save、podman export、podman commit
- 第三方工具:restic、borgbackup、duplicity
- 云备份服务:AWS S3、Google Cloud Storage、Azure Blob Storage
- 企业备份软件:Veritas NetBackup、IBM Spectrum Protect
Part03-生产环境项目实施方案
3.1 容器备份
3.1.1 容器备份配置
# 运行容器
$ podman run -d –name fgedu-nginx \
-p 80:80 \
docker.io/library/nginx
# 导出容器为tar文件
$ podman export fgedu-nginx > fgedu-nginx-backup.tar
# 查看备份文件
$ ls -la fgedu-nginx-backup.tar
# 输出日志
-rw-r–r– 1 root root 157286400 Apr 10 10:00 fgedu-nginx-backup.tar
# 停止并删除容器
$ podman stop fgedu-nginx
$ podman rm fgedu-nginx
# 导入容器
$ cat fgedu-nginx-backup.tar | podman import – fgedu-nginx:backup
# 运行导入的容器
$ podman run -d –name fgedu-nginx \
-p 80:80 \
fgedu-nginx:backup
# 查看容器状态
$ podman ps
# 输出日志
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7890123456ab localhost/fgedu-nginx:backup /bin/sh -c #(nop) 2 minutes ago Up 2 minutes ago 0.0.0.0:80->80/tcp fgedu-nginx
# 提交容器为镜像
$ podman commit fgedu-nginx fgedu-nginx:latest
# 查看镜像
$ podman images
# 输出日志
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/fgedu-nginx latest 1234567890ab 2 minutes ago 150MB
localhost/fgedu-nginx backup 9876543210ab 5 minutes ago 150MB
docker.io/library/nginx latest 7890123456ab 2 weeks ago 142MB
3.2 镜像备份
3.2.1 镜像备份配置
# 拉取镜像
$ podman pull docker.io/library/nginx:latest
# 保存镜像为tar文件
$ podman save -o fgedu-nginx-image-backup.tar docker.io/library/nginx:latest
# 查看备份文件
$ ls -la fgedu-nginx-image-backup.tar
# 输出日志
-rw-r–r– 1 root root 142000000 Apr 10 10:00 fgedu-nginx-image-backup.tar
# 删除镜像
$ podman rmi docker.io/library/nginx:latest
# 加载镜像
$ podman load -i fgedu-nginx-image-backup.tar
# 查看镜像
$ podman images
# 输出日志
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/nginx latest 7890123456ab 2 weeks ago 142MB
# 推送镜像到仓库
$ podman tag docker.io/library/nginx:latest docker.io/fgedu/nginx:latest
$ podman push docker.io/fgedu/nginx:latest
# 从仓库拉取镜像
$ podman rmi docker.io/fgedu/nginx:latest
$ podman pull docker.io/fgedu/nginx:latest
# 查看镜像
$ podman images
# 输出日志
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/fgedu/nginx latest 7890123456ab 2 weeks ago 142MB
3.3 卷备份
3.3.1 卷备份配置
# 创建卷
$ podman volume create fgedu-volume
# 运行容器,使用卷
$ podman run -d –name fgedu-nginx \
-v fgedu-volume:/usr/share/nginx/html:z \
-p 80:80 \
docker.io/library/nginx
# 向卷中写入数据
$ podman exec -it fgedu-nginx sh -c ‘echo “Hello from volume” > /usr/share/nginx/html/index.html’
# 测试数据
$ curl http://localhost
# 输出日志
Hello from volume
# 备份卷
$ podman run –rm \
-v fgedu-volume:/source:z \
-v /Podman/fgdata/backup:/backup:z \
docker.io/library/alpine \
tar -czf /backup/fgedu-volume-backup-$(date +%Y%m%d).tar.gz -C /source .
# 查看备份文件
$ ls -la /Podman/fgdata/backup/
# 输出日志
total 10240
-rw-r–r– 1 root root 10485760 Apr 10 10:00 fgedu-volume-backup-20260410.tar.gz
# 停止并删除容器
$ podman stop fgedu-nginx
$ podman rm fgedu-nginx
# 删除卷
$ podman volume rm fgedu-volume
# 重新创建卷
$ podman volume create fgedu-volume
# 恢复卷
$ podman run –rm \
-v fgedu-volume:/destination:z \
-v /Podman/fgdata/backup:/backup:z \
docker.io/library/alpine \
tar -xzf /backup/fgedu-volume-backup-20260410.tar.gz -C /destination
# 重新运行容器
$ podman run -d –name fgedu-nginx \
-v fgedu-volume:/usr/share/nginx/html:z \
-p 80:80 \
docker.io/library/nginx
# 测试数据是否恢复
$ curl http://localhost
# 输出日志
Hello from volume
Part04-生产案例与实战讲解
4.1 数据库备份
4.1.1 数据库备份实战
# 创建卷用于数据库存储
$ podman volume create fgedu-mysql-data
# 运行MySQL容器
$ podman run -d –name fgedu-mysql \
-v fgedu-mysql-data:/var/lib/mysql:z \
-e MYSQL_ROOT_PASSWORD=fgedu123 \
-e MYSQL_DATABASE=fgedudb \
-e MYSQL_USER=fgedu \
-e MYSQL_PASSWORD=fgedu123 \
-p 3306:3306 \
docker.io/library/mysql:8.0
# 测试数据库
$ podman exec -it fgedu-mysql mysql -u fgedu -p fgedudb
# 输出日志
Enter password:
mysql> CREATE TABLE fgedu_test (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> name VARCHAR(255),
-> value VARCHAR(255)
-> );
mysql> INSERT INTO fgedu_test (name, value) VALUES
-> (‘test1’, ‘value1’),
-> (‘test2’, ‘value2’),
-> (‘test3’, ‘value3’);
mysql> SELECT * FROM fgedu_test;
# 输出日志
+—-+——-+——–+
| id | name | value |
+—-+——-+——–+
| 1 | test1 | value1 |
| 2 | test2 | value2 |
| 3 | test3 | value3 |
+—-+——-+——–+
mysql> exit
# 停止容器
$ podman stop fgedu-mysql
# 备份卷
$ podman run –rm \
-v fgedu-mysql-data:/source:z \
-v /Podman/fgdata/backup:/backup:z \
docker.io/library/alpine \
tar -czf /backup/fgedu-mysql-backup-$(date +%Y%m%d).tar.gz -C /source .
# 查看备份文件
$ ls -la /Podman/fgdata/backup/
# 输出日志
total 20480
-rw-r–r– 1 root root 20971520 Apr 10 10:00 fgedu-mysql-backup-20260410.tar.gz
# 删除卷
$ podman volume rm fgedu-mysql-data
# 重新创建卷
$ podman volume create fgedu-mysql-data
# 恢复卷
$ podman run –rm \
-v fgedu-mysql-data:/destination:z \
-v /Podman/fgdata/backup:/backup:z \
docker.io/library/alpine \
tar -xzf /backup/fgedu-mysql-backup-20260410.tar.gz -C /destination
# 重新运行容器
$ podman run -d –name fgedu-mysql \
-v fgedu-mysql-data:/var/lib/mysql:z \
-e MYSQL_ROOT_PASSWORD=fgedu123 \
-e MYSQL_DATABASE=fgedudb \
-e MYSQL_USER=fgedu \
-e MYSQL_PASSWORD=fgedu123 \
-p 3306:3306 \
docker.io/library/mysql:8.0
# 测试数据是否恢复
$ podman exec -it fgedu-mysql mysql -u fgedu -p fgedudb
# 输出日志
Enter password:
mysql> SELECT * FROM fgedu_test;
# 输出日志
+—-+——-+——–+
| id | name | value |
+—-+——-+——–+
| 1 | test1 | value1 |
| 2 | test2 | value2 |
| 3 | test3 | value3 |
+—-+——-+——–+
mysql> exit
4.2 应用备份
4.2.1 应用备份实战
# 创建主机目录用于应用存储
$ mkdir -p /Podman/fgdata/app
# 创建应用文件
$ cat > /Podman/fgdata/app/server.js << EOF
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
const port = 3000;
const dataPath = path.join(__dirname, 'data.json');
// 初始化数据
if (!fs.existsSync(dataPath)) {
fs.writeFileSync(dataPath, JSON.stringify({ users: [] }));
}
// 读取数据
app.get('/users', (req, res) => {
const data = JSON.parse(fs.readFileSync(dataPath, ‘utf8’));
res.json(data);
});
// 添加用户
app.post(‘/users’, (req, res) => {
const data = JSON.parse(fs.readFileSync(dataPath, ‘utf8’));
const newUser = { id: Date.now(), name: `User${Date.now()}` };
data.users.push(newUser);
fs.writeFileSync(dataPath, JSON.stringify(data));
res.json(newUser);
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
EOF
# 创建package.json
$ cat > /Podman/fgdata/app/package.json << EOF
{
"name": "node-app",
"version": "1.0.0",
"description": "Node.js application",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.18.2"
}
}
EOF
# 运行Node.js容器
$ podman run -d --name fgedu-node \
-v /Podman/fgdata/app:/app:z \
-p 3000:3000 \
-w /app \
docker.io/library/node:18-alpine \
sh -c "npm install && npm start"
# 测试应用
$ curl http://localhost:3000/users
# 输出日志
{"users":[]}
# 添加用户
$ curl -X POST http://localhost:3000/users
# 输出日志
{"id":1234567890123,"name":"User1234567890123"}
# 查看数据
$ curl http://localhost:3000/users
# 输出日志
{"users":[{"id":1234567890123,"name":"User1234567890123"}]}
# 备份应用数据
$ tar -czf /Podman/fgdata/backup/fgedu-app-backup-$(date +%Y%m%d).tar.gz -C /Podman/fgdata/app .
# 查看备份文件
$ ls -la /Podman/fgdata/backup/
# 输出日志
total 10240
-rw-r--r-- 1 root root 10485760 Apr 10 10:00 fgedu-app-backup-20260410.tar.gz
# 停止容器
$ podman stop fgedu-node
# 删除应用数据
$ rm -rf /Podman/fgdata/app/*
# 恢复应用数据
$ tar -xzf /Podman/fgdata/backup/fgedu-app-backup-20260410.tar.gz -C /Podman/fgdata/app
# 重新运行容器
$ podman run -d --name fgedu-node \
-v /Podman/fgdata/app:/app:z \
-p 3000:3000 \
-w /app \
docker.io/library/node:18-alpine \
sh -c "npm start"
# 测试数据是否恢复
$ curl http://localhost:3000/users
# 输出日志
{"users":[{"id":1234567890123,"name":"User1234567890123"}]}
4.3 系统备份
4.3.1 系统备份实战
# 安装restic
$ sudo dnf install -y restic
# 初始化restic仓库
$ restic init –repo /Podman/fgdata/backup/restic
# 备份Podman配置和数据
$ restic backup –repo /Podman/fgdata/backup/restic \
/etc/containers \
/var/lib/containers \
/Podman/fgdata
# 查看备份
$ restic snapshots –repo /Podman/fgdata/backup/restic
# 输出日志
ID Time Host Tags Paths
————————————————————
12345678 2026-04-10 10:00:00 fgedu.net.cn /etc/containers, /var/lib/containers, /Podman/fgdata
————————————————————
1 snapshots
# 恢复备份
$ restic restore –repo /Podman/fgdata/backup/restic \
–target / \
12345678
# 测试恢复
$ podman ps
# 输出日志
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7890123456ab docker.io/library/nginx nginx -g daemon 2 minutes ago Up 2 minutes ago 0.0.0.0:80->80/tcp fgedu-nginx
1234567890ab docker.io/library/mysql mysqld 2 minutes ago Up 2 minutes ago 0.0.0.0:3306->3306/tcp fgedu-mysql
5678901234ab docker.io/library/node sh -c npm start 2 minutes ago Up 2 minutes ago 0.0.0.0:3000->3000/tcp fgedu-node
# 自动化备份脚本
$ cat > /Podman/app/scripts/backup.sh << EOF
#!/bin/bash
# backup.sh
# from:www.itpux.com.qq113257174.wx:itpux-com
# web: http://www.fgedu.net.cn
# 定义变量
BACKUP_DIR="/Podman/fgdata/backup"
RESTIC_REPO="$BACKUP_DIR/restic"
DATE=$(date +%Y%m%d)
# 创建备份目录
mkdir -p $BACKUP_DIR
# 初始化restic仓库(如果不存在)
if [ ! -d "$RESTIC_REPO" ]; then
restic init --repo $RESTIC_REPO
fi
# 备份Podman配置和数据
restic backup --repo $RESTIC_REPO \
/etc/containers \
/var/lib/containers \
/Podman/fgdata
# 清理旧备份(保留最近7天)
restic forget --repo $RESTIC_REPO \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 12
# 验证备份
restic check --repo $RESTIC_REPO
# 输出备份完成信息
echo "Backup completed successfully on $DATE"
EOF
# 添加执行权限
$ chmod +x /Podman/app/scripts/backup.sh
# 运行备份脚本
$ /Podman/app/scripts/backup.sh
# 输出日志
repository 12345678 opened successfully, password is correct
created new cache in /root/.cache/restic
no parent snapshot found, will read all files
[0:00] 100.00% 100 files, 100MB, 100 chunks
duration: 0:00, 100MB/s
Snapshot 87654321 saved
repository 12345678 opened successfully, password is correct
Applying Policy: keep 7 daily, 4 weekly, 12 monthly snapshots
keep 1 snapshots: 87654321
remove 0 snapshots
repository 12345678 opened successfully, password is correct
created new cache in /root/.cache/restic
check all packs
check snapshots, trees and blobs
no errors were found
Backup completed successfully on 20260410
Part05-风哥经验总结与分享
5.1 备份最佳实践
Podman容器备份的最佳实践:
- 定期备份:定期执行备份,确保数据的安全性
- 多份备份:创建多份备份,存储在不同的位置
- 验证备份:定期验证备份的完整性和可恢复性
- 自动化备份:使用脚本自动化备份过程
- 备份策略:根据数据重要性制定不同的备份策略
- 备份监控:监控备份过程,及时发现和解决备份问题
- 备份文档:记录备份配置和恢复流程,便于维护和追溯
- 测试恢复:定期测试恢复过程,确保恢复正常
5.2 恢复最佳实践
Podman容器恢复的最佳实践:
## 恢复准备
– 准备恢复环境:确保恢复环境的配置与原环境一致
– 备份验证:验证备份的完整性和可恢复性
– 恢复计划:制定详细的恢复计划
– 恢复测试:在测试环境中测试恢复过程
## 恢复执行
– 停止相关服务:停止与恢复相关的服务
– 恢复数据:按照恢复计划恢复数据
– 验证恢复:验证恢复的数据是否正确
– 启动服务:启动恢复后的服务
– 测试服务:测试恢复后的服务是否正常运行
## 恢复后处理
– 监控服务:监控恢复后的服务运行状态
– 数据验证:验证恢复的数据完整性
– 文档更新:更新恢复文档和记录
– 恢复演练:定期进行恢复演练,确保恢复计划的有效性
## 常见恢复场景
– 容器故障:恢复容器到正常状态
– 数据丢失:恢复丢失的数据
– 系统故障:恢复系统到正常状态
– 灾难恢复:在灾难发生后恢复系统
5.3 备份故障排查
Podman容器备份的故障排查:
## 备份失败
– 检查存储空间:df -h
– 检查权限:ls -la
– 检查网络连接:ping
– 检查备份工具:restic –version
– 查看备份日志:restic backup –repo
## 恢复失败
– 检查备份文件:ls -la
– 检查权限:ls -la
– 检查存储空间:df -h
– 检查恢复工具:restic –version
– 查看恢复日志:restic restore –repo
## 备份性能问题
– 检查备份速度:使用time命令测量备份时间
– 优化备份配置:调整备份工具的配置参数
– 增加存储带宽:使用高速存储设备
– 减少备份数据:只备份必要的数据
## 备份存储问题
– 检查存储使用:df -h
– 清理旧备份:restic forget –repo
– 增加存储容量:扩展存储设备
– 压缩备份数据:使用压缩算法减少存储占用
## 备份安全问题
– 检查备份权限:ls -la
– 加密备份数据:使用加密算法保护备份数据
– 限制备份访问:限制备份的访问权限
– 审计备份操作:记录备份的访问和操作
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
