Skip to content

数据卷

容器的文件系统是临时的,容器删除后其中的数据也随之消失。数据卷(Volume)是 Docker 提供的数据持久化机制。

为什么需要数据卷

无数据卷(容器删除后数据丢失):
┌─────────────┐
│  Container  │  删除容器 → 数据消失 ❌
│  /var/data  │
└─────────────┘

使用数据卷(数据独立于容器):
┌─────────────┐      ┌──────────────────┐
│  Container  │      │   Docker Volume  │
│  /var/data  ├──────▶  /var/lib/docker │  删除容器 → 数据保留 ✅
└─────────────┘      │  /volumes/xxx    │
                     └──────────────────┘

数据卷的特点:

  • 持久化:容器删除后数据依然存在
  • 共享:多个容器可以挂载同一个数据卷
  • 隔离:数据卷不增加容器镜像的大小
  • 高效:读写性能优于绑定挂载(在 macOS/Windows 上)

三种挂载方式

类型说明适用场景
Volume(数据卷)由 Docker 管理,存储在 Docker 目录下生产环境数据持久化
Bind Mount(绑定挂载)挂载宿主机任意目录开发时同步代码
tmpfs Mount仅存于内存,容器停止即清除临时敏感数据

Volume(数据卷)

创建和管理数据卷

bash
# 创建数据卷
docker volume create my-data

# 列出所有数据卷
docker volume ls

# 查看数据卷详情
docker volume inspect my-data

# 删除数据卷
docker volume rm my-data

# 删除所有未使用的数据卷
docker volume prune

docker volume inspect 输出:

json
[
  {
    "CreatedAt": "2024-01-01T00:00:00Z",
    "Driver": "local",
    "Labels": {},
    "Mountpoint": "/var/lib/docker/volumes/my-data/_data",
    "Name": "my-data",
    "Options": {},
    "Scope": "local"
  }
]

挂载数据卷到容器

bash
# 挂载命名卷(-v 卷名:容器路径)
docker run -d \
  --name my-mysql \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  mysql:8.0

# 使用 --mount 语法(更明确,推荐)
docker run -d \
  --name my-mysql \
  --mount type=volume,source=mysql-data,target=/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  mysql:8.0

# 挂载匿名卷(Docker 自动生成卷名)
docker run -d -v /var/lib/mysql mysql:8.0

多容器共享数据卷

bash
# 创建共享卷
docker volume create shared-data

# 容器 1 写入数据
docker run -d --name writer \
  -v shared-data:/data \
  alpine sh -c "while true; do echo \$(date) >> /data/log.txt; sleep 1; done"

# 容器 2 读取数据
docker run -it --name reader \
  -v shared-data:/data \
  alpine tail -f /data/log.txt

Bind Mount(绑定挂载)

将宿主机的目录或文件直接挂载到容器中:

bash
# 挂载目录(-v 宿主机路径:容器路径)
docker run -d \
  --name web \
  -v /home/user/html:/usr/share/nginx/html \
  -p 80:80 \
  nginx

# 使用 --mount 语法
docker run -d \
  --name web \
  --mount type=bind,source=/home/user/html,target=/usr/share/nginx/html \
  -p 80:80 \
  nginx

# 只读挂载(容器内不可写)
docker run -d \
  -v /home/user/config:/etc/app/config:ro \
  myapp

# 挂载单个文件
docker run -d \
  -v /home/user/nginx.conf:/etc/nginx/nginx.conf:ro \
  nginx

开发环境典型用法:挂载代码目录,修改代码无需重新构建镜像:

bash
# Node.js 开发
docker run -d \
  --name node-dev \
  -v $(pwd):/app \
  -w /app \
  -p 3000:3000 \
  node:20 npm run dev

数据卷与绑定挂载的对比

特性VolumeBind Mount
存储位置Docker 管理目录宿主机任意目录
创建方式Docker 管理宿主机文件系统
是否需要提前创建否(自动创建)否(自动创建目录)
共享能力多容器共享多容器共享
备份相对复杂直接备份宿主机目录
适用场景生产持久化开发调试
macOS/Windows 性能较好较差

数据卷备份与恢复

备份数据卷

bash
# 方法:启动临时容器,将数据卷内容打包
docker run --rm \
  -v mysql-data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/mysql-backup.tar.gz -C /data .

# 备份成功后查看
ls -lh mysql-backup.tar.gz

恢复数据卷

bash
# 创建新数据卷
docker volume create mysql-data-restore

# 解压备份到新数据卷
docker run --rm \
  -v mysql-data-restore:/data \
  -v $(pwd):/backup \
  alpine tar xzf /backup/mysql-backup.tar.gz -C /data

数据卷迁移(跨主机)

bash
# 在源主机:导出数据卷
docker run --rm \
  -v old-volume:/data \
  alpine tar czf - -C /data . > volume-backup.tar.gz

# 将 volume-backup.tar.gz 传输到目标主机

# 在目标主机:导入数据卷
docker volume create new-volume
cat volume-backup.tar.gz | docker run --rm -i \
  -v new-volume:/data \
  alpine tar xzf - -C /data

tmpfs 挂载

仅存储在内存中,容器停止后数据消失,适合存储临时敏感数据:

bash
docker run -d \
  --mount type=tmpfs,destination=/tmp,tmpfs-size=100m \
  nginx

常见使用场景

MySQL 数据持久化

bash
docker run -d \
  --name mysql \
  --restart unless-stopped \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=mydb \
  -v mysql-data:/var/lib/mysql \
  -p 3306:3306 \
  mysql:8.0

Nginx 静态文件服务

bash
docker run -d \
  --name nginx \
  -v /var/www/html:/usr/share/nginx/html:ro \
  -v /etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
  -p 80:80 \
  nginx

配置文件挂载

bash
docker run -d \
  --name app \
  -v /etc/myapp/config.yml:/app/config.yml:ro \
  myapp:latest

总结

数据持久化是容器化应用的关键问题:

  • Volume 是生产环境的首选,由 Docker 管理,使用简单
  • Bind Mount 适合开发环境,代码修改即时生效
  • 重要数据一定要挂载到卷或绑定挂载,避免数据丢失
  • 定期备份重要数据卷

下一节介绍 Docker 网络管理。