容器退出后数据持久化
面试题
容器退出后,容器内产生的数据会丢失吗?如何保证数据在容器生命周期结束后依然存在?
标准答案
容器退出后,容器文件系统的变更默认会保留在磁盘上(除非使用了 --rm),但一旦容器被 docker rm 删除,这些数据就彻底丢失了。要实现真正的数据持久化,核心方式是使用 Docker 数据卷(Volume)或绑定挂载(Bind Mount)。
容器文件系统的生命周期
# 实验:演示容器数据的生存周期
# 1. 创建容器并写入数据
docker run --name demo alpine sh -c "echo 'hello world' > /data/test.txt"
# 2. 容器虽然退出了,但数据还在
docker start demo
docker exec demo cat /data/test.txt
# 输出:hello world
# 3. 删除容器后数据丢失
docker rm demo
# 重新创建同名容器,刚才的数据已经没了
docker run --name demo alpine cat /data/test.txt
# 输出:cat: can't open '/data/test.txt': No such file or directory
结论:容器存活 ≠ 数据安全;容器删除 = 数据丢失。
三种持久化方式
1. 数据卷(Volume)
# 创建数据卷
docker volume create mydata
# 使用数据卷
docker run -d --name db \
-v mydata:/var/lib/mysql \
mysql:8
# 即使容器被删除,数据卷依然存在
docker rm -f db
docker run -d --name new-db \
-v mydata:/var/lib/mysql \
mysql:8
# 数据完全恢复!
2. 绑定挂载(Bind Mount)
# 将宿主机目录挂载到容器内
docker run -d --name web \
-v /host/data:/usr/share/nginx/html:ro \
nginx
# 数据在宿主机上,容器删除不影响
# 但是需要手动管理宿主机目录权限
3. tmpfs 挂载(仅内存)
# 数据存在内存中,容器退出即丢失
# 适合临时缓存,不适合持久化
docker run -d --name cache \
--tmpfs /cache:rw,noexec,nosuid,size=64m \
myapp
关键确认:退出容器 ≠ 删除容器
很多人在这个问题上混淆:
# 退出(exit)的容器
docker run alpine echo hello # 运行完退出,状态变成 Exited
docker ps -a # 容器还在,数据还在
docker start # 可以重新启动,数据完好
# 删除(rm)的容器
docker rm # 容器被删除,数据(无卷时)丢失
# 只有 docker rm 才会清理数据
生产环境持久化方案
数据库类(有状态服务)
# docker-compose.yml
services:
mysql:
image: mysql:8
volumes:
- mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: rootpass
volumes:
mysql-data: # 具名数据卷
应用日志类
services:
nginx:
image: nginx:alpine
volumes:
- app-logs:/var/log/nginx
- app-data:/usr/share/nginx/html
volumes:
app-logs:
app-data:
配置文件类
services:
nginx:
image: nginx:alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro # bind mount
- ./html:/usr/share/nginx/html:ro
数据恢复场景
# 场景:容器意外被删除,但使用了命名数据卷
docker run -d --name db -v pgdata:/var/lib/postgresql/data postgres:15
# 不小心删除了容器
docker rm -f db
# 数据卷还在!
docker volume ls | grep pgdata
# 创建新容器,挂载同一数据卷
docker run -d --name new-db -v pgdata:/var/lib/postgresql/data postgres:15
# 数据库数据完全恢复,无需备份
常见误区
误区 1:docker commit 可以持久化数据
# 不完全正确。commit 保存的是镜像层,不是数据卷
# 数据卷内的数据不会包含在 commit 结果中
docker run -v mydata:/data alpine sh -c "echo data > /data/file"
docker commit my-container myimage:latest
docker run myimage:latest cat /data/file # 文件不存在!
误区 2:容器退出后因为用了 –rm 数据就丢了
# --rm 只在容器退出时自动删除容器,不影响数据卷
docker run --rm -v mydata:/data alpine sh -c "echo hello > /data/test"
# 容器自动删除,但 mydata 卷还在
docker run --rm -v mydata:/data alpine cat /data/test # hello 还在
最佳实践
# 1. 有状态服务一定要用命名数据卷
-v appdata:/app/data
# 2. 配置文件用绑定挂载
-v ./config:/app/config:ro
# 3. 临时缓存用 tmpfs
--tmpfs /tmp:size=100m
# 4. 养成定期备份数据卷的习惯
docker run --rm -v mydata:/source -v $(pwd):/backup alpine \
tar czf /backup/mydata-$(date +%Y%m%d).tar.gz -C /source .
面试追问
问:如何判断一个容器的数据是否持久化了?
# 查看容器的挂载信息
docker inspect --format='{{json .Mounts}}' myapp | jq .
# 如果有 Mounts 输出,表示有持久化配置
# 如果为空,数据随容器生命周期
# 也可以用 docker inspect 看 Volumes 和 Binds 字段
问:同时用 –rm 和数据卷,容器退出后数据卷还在吗?
在。--rm 只删除容器本身(含容器文件系统),数据卷是独立生命周期对象,不受影响。
总结
容器退出不等于数据丢失,容器删除才是关键。三个核心认知:数据卷独立于容器生命周期、命名数据卷是生产环境首选、退出容器可重新启动保留数据。要问自己:如果这个容器被删了,它的数据还在不在?
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容