容器退出后数据持久化

容器退出后数据持久化

面试题

容器退出后,容器内产生的数据会丢失吗?如何保证数据在容器生命周期结束后依然存在?

标准答案

容器退出后,容器文件系统的变更默认会保留在磁盘上(除非使用了 --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
喜欢就支持一下吧
点赞15 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容