Skip to content

Docker 存储

容器文件系统是临时的(可写层),容器删除后数据随之消失。本文讲解 Docker 的三种数据持久化方式及实战。

存储类型对比

方式命令/语法生命周期典型用途
数据卷 Volume-v myvol:/data独立于容器,需显式删除数据库数据、共享数据
绑定挂载 Bind mount-v /host/path:/data跟随宿主机文件配置文件、开发热重载
tmpfs--tmpfs /tmp仅内存,容器停即失敏感临时文件、密钥

数据卷 Volume

Volume 由 Docker 管理,位于 /var/lib/docker/volumes/,是最推荐的持久化方式。

bash
# 创建
docker volume create mydata

# 使用
docker run -d --name db -v mydata:/var/lib/mysql mysql:8

# 查看详情(含宿主机实际路径)
docker volume inspect mydata

# 列出 / 删除
docker volume ls
docker volume rm mydata
docker volume prune   # 删除未被引用的卷

多容器共享同一卷:

bash
docker run -d --name writer -v shared:/data busybox sh -c "while true; do date >> /data/log; sleep 1; done"
docker run -d --name reader -v shared:/data busybox cat /data/log

绑定挂载 Bind mount

直接把宿主机目录/文件挂进容器,适合挂载配置与开发调试:

bash
# 挂载目录
docker run -d -v $(pwd)/html:/usr/share/nginx/html nginx

# 只读挂载(推荐配置类)
docker run -d -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro nginx

# 挂载单个文件
docker run -d -v /etc/localtime:/etc/localtime:ro myapp

生产环境挂载配置文件建议加 :ro 只读,防止容器误写宿主机。

tmpfs 挂载

仅存在于内存,适合存临时密钥:

bash
docker run -d --tmpfs /run/secrets:size=1m myapp

容器可写层与存储驱动

容器对文件系统的修改发生在可写层(upperdir),由存储驱动(overlay2 等)管理。重要结论:

  • 写入可写层性能差且不可持久,数据库等 IO 密集场景务必挂 Volume。
  • 生产环境 --storage-driver 推荐 overlay2(默认)。

查看存储驱动:

bash
docker info | grep "Storage Driver"

磁盘占用与日志轮转

Docker 默认不对容器 stdout/stderr 日志做限制,可能打满磁盘。配置 /etc/docker/daemon.json

json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

注意:JSON 配置中注释需独立成行,勿写行尾注释。修改后 sudo systemctl restart docker

每个容器单独限制日志:

yaml
# docker-compose.yml
services:
  app:
    image: myapp
    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "3"

清理磁盘:

bash
docker system df          # 查看占用
docker system prune -a --volumes   # 清理未使用资源

最佳实践

  1. 数据库、消息队列等有状态服务一律使用 Volume。
  2. 配置文件用 Bind mount 且尽量 :ro
  3. 配置日志轮转,避免磁盘被撑满。
  4. 生产环境将 /var/lib/docker 挂载到大容量独立磁盘。
  5. 删除容器时若需连带删匿名卷用 docker rm -v