Appearance
数据卷
容器的文件系统是临时的,容器删除后其中的数据也随之消失。数据卷(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 prunedocker 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.txtBind 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数据卷与绑定挂载的对比
| 特性 | Volume | Bind 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 /datatmpfs 挂载
仅存储在内存中,容器停止后数据消失,适合存储临时敏感数据:
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.0Nginx 静态文件服务
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 网络管理。