← 全部文章
Docker存储数据卷

Docker 系列(五):数据持久化 Volume 与 Bind Mount

2026年7月24日 · 12 分钟

为什么需要数据持久化

回顾第三篇的原理:容器 = 只读镜像层 + 一个可写层,而可写层随容器删除而消失

这意味着一个致命问题:

docker run -d --name db postgres        # 跑个数据库
# ... 写入了一堆重要数据 ...
docker rm -f db                          # 容器删了
# 💥 数据全没了!

对于数据库、上传文件、日志这类需要长期保存的数据,我们必须把它们存到容器之外。 Docker 提供了三种方式。

三种数据挂载方式

┌──────────────────────────────────────────────┐
│                  宿主机                         │
│                                                │
│   /var/lib/docker/volumes/  ← Volume(Docker 管理)│
│   /home/user/data/          ← Bind Mount(你指定)  │
│                                                │
│         内存                 ← tmpfs(不落盘)    │
└──────────────────────────────────────────────┘
类型存储位置谁管理适用场景
Volume(卷)Docker 专属目录Docker生产首选,数据库、持久数据
Bind Mount(绑定挂载)你指定的宿主机路径你自己开发时挂源码、挂配置文件
tmpfs内存Docker临时敏感数据,不需落盘

一、Volume(推荐)

Volume 由 Docker 统一管理,存放在 Docker 的专属目录,你不用关心具体物理路径。

# 创建一个卷
docker volume create mydata

# 查看所有卷
docker volume ls

# 挂载到容器:-v 卷名:容器内路径
docker run -d --name db -v mydata:/var/lib/postgresql/data postgres

# 查看卷详情(包括真实路径)
docker volume inspect mydata

# 删除卷(容器还在用时删不掉)
docker volume rm mydata

即使 docker rm -f db 删掉容器,mydata 卷里的数据依然安在。下次挂载同一个卷, 数据原封不动。

二、Bind Mount(绑定挂载)

直接把宿主机上的某个目录/文件挂进容器。开发时特别有用——改本机代码,容器里立刻生效。

# -v 宿主机绝对路径:容器内路径
docker run -d -p 8080:80 -v /home/user/site:/usr/share/nginx/html nginx

# Windows PowerShell 里用当前目录
docker run -d -p 8080:80 -v ${PWD}:/usr/share/nginx/html nginx

现在你在宿主机 /home/user/site 里改任何文件,刷新网页就能看到——非常适合本地开发。

只读挂载:加 :ro 后缀让容器无法修改,如 -v /host/config:/app/config:ro, 常用于挂配置文件。

三、-v 与 --mount 两种语法

老语法 -v 简洁,新语法 --mount 更明确(推荐脚本/生产用):

# -v 简写
docker run -v mydata:/data ...

# --mount 显式写法,含义一目了然
docker run --mount type=volume,source=mydata,target=/data ...
docker run --mount type=bind,source=/host/path,target=/data ...

实战:给 PostgreSQL 持久化数据

# 1. 创建专用卷
docker volume create pgdata

# 2. 启动数据库,挂载卷 + 设置密码
docker run -d --name pg \
  -e POSTGRES_PASSWORD=secret \
  -p 5432:5432 \
  -v pgdata:/var/lib/postgresql/data \
  postgres:16

# 3. 连进去建张表、写点数据(略)

# 4. 模拟"服务器重装":删掉容器
docker rm -f pg

# 5. 用同一个卷重新启动
docker run -d --name pg \
  -e POSTGRES_PASSWORD=secret \
  -p 5432:5432 \
  -v pgdata:/var/lib/postgresql/data \
  postgres:16

# ✅ 之前的表和数据都还在!

数据备份与恢复

Volume 的数据可以借助一个临时容器打包备份:

# 备份 pgdata 卷到当前目录的 backup.tar
docker run --rm \
  -v pgdata:/data \
  -v ${PWD}:/backup \
  alpine tar czf /backup/backup.tar -C /data .

# 恢复:把 backup.tar 解压回一个卷
docker run --rm \
  -v pgdata:/data \
  -v ${PWD}:/backup \
  alpine tar xzf /backup/backup.tar -C /data

思路很巧妙:起一个临时 alpine 容器,同时挂上「数据卷」和「宿主机目录」,用 tar 在两者之间搬运数据。

本篇小结

  • 容器可写层随删除消失,持久数据必须挂到容器之外。
  • Volume:Docker 管理,生产首选;Bind Mount:挂宿主机路径,开发挂源码/配置; tmpfs:内存临时数据。
  • -v 卷名:容器路径 用卷,-v 宿主路径:容器路径 是绑定挂载,:ro 设只读。
  • 数据库务必挂卷,否则重建容器数据全丢;可用临时容器 + tar 做备份恢复。

数据能存了,下一篇解决容器之间怎么「通信」——Docker 网络

相关水晶