跳到主要内容

Docker 存储

存储类型对比

类型位置持久化性能适用场景
VolumesDocker 管理目录最佳数据库、应用数据
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 推荐
btrfsBtrfs 文件系统Btrfs 用户
zfsZFS 文件系统ZFS 用户
devicemapper块设备映射❌ 已弃用
# 查看当前存储驱动
docker info | grep "Storage Driver"

# 配置存储驱动
cat /etc/docker/daemon.json
{
"storage-driver": "overlay2"
}

常见面试问题

Q1: Docker Volume 和 Bind Mount 的区别?

答案

维度VolumeBind Mount
管理方Docker 引擎用户自行管理
位置/var/lib/docker/volumes/宿主机任意路径
可移植性✅ 跨平台一致❌ 依赖宿主机路径
备份Docker CLI 操作直接文件操作
驱动支持远程存储驱动仅本地文件系统
推荐场景持久化数据(数据库)开发、配置文件

Q2: 如何保证容器数据不丢失?

答案

  1. 使用命名卷存储关键数据
  2. 定期自动化备份
  3. docker compose down 不加 -v(不删除卷)
  4. 数据库开启主从复制/WAL 日志
  5. 生产环境使用外部存储(NFS、Ceph、云存储)

Q3: 容器的存储层(可写层)有什么特点?

答案

  • 容器层采用 Copy-on-Write(写时复制)
  • 读操作直接读镜像层,写操作复制到容器层修改
  • 容器删除后,可写层数据丢失
  • 频繁写操作影响性能,应使用 Volume 替代

相关链接