Docker 存储
存储类型对比
| 类型 | 位置 | 持久化 | 性能 | 适用场景 |
|---|---|---|---|---|
| Volumes | Docker 管理目录 | ✅ | 最佳 | 数据库、应用数据 |
| Bind Mounts | 宿主机任意路径 | ✅ | 好 | 开发热重载、配置文件 |
| tmpfs | 内存 | ❌ | 最快 | 临时文件、敏感信息 |
Volumes(命名卷)
Docker 管理的数据卷,是持久化数据的推荐方式。
# ===== 卷管理 =====
docker volume create mydata # 创建卷
docker volume ls # 列出所有卷
docker volume inspect mydata # 查看卷详情
docker volume rm mydata # 删除卷
docker volume prune # 清理未使用的卷
# ===== 使用卷 =====
# 命名卷(推荐)
docker run -d -v mydata:/var/lib/postgresql/data postgres:16
# 匿名卷(不推荐,难以管理)
docker run -d -v /var/lib/postgresql/data postgres:16
Volume 在 Compose 中使用
compose.yml
services:
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data # 命名卷
redis:
image: redis:7
volumes:
- redis-data:/data
volumes:
db-data: # 声明命名卷
driver: local # 默认驱动
redis-data:
driver: local
driver_opts: # 驱动选项
type: none
device: /data/redis
o: bind
Bind Mounts(绑定挂载)
将宿主机目录直接挂载到容器内,适合开发环境。
# 绑定挂载
docker run -d \
-v /host/path:/container/path \ # 可读写
-v /host/config:/etc/app/config:ro \ # 只读
myapp
# --mount 语法(更明确,推荐)
docker run -d \
--mount type=bind,source=/host/path,target=/container/path \
--mount type=bind,source=/host/config,target=/etc/app/config,readonly \
myapp
开发热重载
绑定挂载常用于开发环境,源码修改后容器内实时生效:
compose.dev.yml
services:
web:
build: .
volumes:
- .:/app # 源码挂载
- /app/node_modules # 匿名卷排除 node_modules
command: npm run dev
tmpfs(内存挂载)
数据仅存在于内存中,容器停止后丢失。
docker run -d \
--tmpfs /tmp:size=100m,mode=1777 \
myapp
# --mount 语法
docker run -d \
--mount type=tmpfs,destination=/tmp,tmpfs-size=100m \
myapp
适用场景:
- 临时文件缓存
- 敏感信息(不写入磁盘)
- 高速 I/O 需求
数据备份与恢复
备份 Volume
# 方法 1:挂载卷到临时容器,tar 打包
docker run --rm \
-v mydata:/source:ro \
-v $(pwd):/backup \
alpine tar czf /backup/mydata-$(date +%Y%m%d).tar.gz -C /source .
# 方法 2:docker cp
docker cp container_name:/var/lib/postgresql/data ./backup/
恢复 Volume
# 创建新卷并恢复
docker volume create mydata-restored
docker run --rm \
-v mydata-restored:/target \
-v $(pwd):/backup:ro \
alpine sh -c "cd /target && tar xzf /backup/mydata-20240101.tar.gz"
自动化备份脚本
backup-volumes.sh
#!/bin/bash
BACKUP_DIR="/backups/docker"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"
# 备份所有命名卷
for vol in $(docker volume ls -q); do
echo "Backing up volume: $vol"
docker run --rm \
-v "$vol":/source:ro \
-v "$BACKUP_DIR":/backup \
alpine tar czf "/backup/${vol}_${DATE}.tar.gz" -C /source .
done
# 清理 7 天前的备份
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete
echo "Backup completed: $BACKUP_DIR"
存储驱动(Storage Driver)
存储驱动决定 Docker 如何管理镜像层和容器可写层。
| 驱动 | 说明 | 推荐 |
|---|---|---|
overlay2 | 默认驱动,性能好 | ✅ Linux 推荐 |
btrfs | Btrfs 文件系统 | Btrfs 用户 |
zfs | ZFS 文件系统 | ZFS 用户 |
devicemapper | 块设备映射 | ❌ 已弃用 |
# 查看当前存储驱动
docker info | grep "Storage Driver"
# 配置存储驱动
cat /etc/docker/daemon.json
{
"storage-driver": "overlay2"
}
常见面试问题
Q1: Docker Volume 和 Bind Mount 的区别?
答案:
| 维度 | Volume | Bind Mount |
|---|---|---|
| 管理方 | Docker 引擎 | 用户自行管理 |
| 位置 | /var/lib/docker/volumes/ | 宿主机任意路径 |
| 可移植性 | ✅ 跨平台一致 | ❌ 依赖宿主机路径 |
| 备份 | Docker CLI 操作 | 直接文件操作 |
| 驱动 | 支持远程存储驱动 | 仅本地文件系统 |
| 推荐场景 | 持久化数据(数据库) | 开发、配置文件 |
Q2: 如何保证容器数据不丢失?
答案:
- 使用命名卷存储关键数据
- 定期自动化备份
docker compose down不加-v(不删除卷)- 数据库开启主从复制/WAL 日志
- 生产环境使用外部存储(NFS、Ceph、云存储)
Q3: 容器的存储层(可写层)有什么特点?
答案:
- 容器层采用 Copy-on-Write(写时复制)
- 读操作直接读镜像层,写操作复制到容器层修改
- 容器删除后,可写层数据丢失
- 频繁写操作影响性能,应使用 Volume 替代