Docker数据管理
Docker 容器默认是无状态的,容器删除后数据也随之消失。那么生产环境中如何实现数据持久化?如何在容器之间安全地共享数据?本文将从零开始,系统讲解 Docker 的四种数据管理方式:数据卷(Volumes)、数据卷容器(已过时)、绑定挂载(Bind Mounts)、临时挂载(tmpfs),通过实操演示每种方式的使用场景和注意事项。最后还会手把手教你使用 --volumes-from + tar 实现数据的备份与恢复,这套方案也是生产环境中最常用的数据备份方式。
4种:数据卷管理
数据卷容器管理(old)
绑定挂载
临时挂载
1.数据卷操作
1.创建数据卷
bash
[root@bogon ~]# docker volume create myvol
myvol
2.查看卷详细信息
bash
[root@bogon ~]# docker volume inspect myvol
[
{
"CreatedAt": "2026-04-12T20:39:23+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/data/docker/volumes/myvol/_data",
"Name": "myvol",
"Options": null,
"Scope": "local"
}
]
[ro
3.使用数据卷
创建容器时,带参数: -v 数据卷:容器内部路径
bash
[root@bogon ~]# docker run --name nginx1 -d -p 80:80 -v myvol:/usr/share/nginx/html nginx:latest
4.验证数据
bash
[root@bogon ~]# ls /data/docker/volumes/myvol/_data
50x.html index.html
[root@bogon ~]# docker exec -it nginx1 ls /usr/share/nginx/html
50x.html index.html
#修改主页
[root@bogon ~]# docker exec -it nginx1 sh
# echo welcome nginx > /usr/share/nginx/html/index.html
# curl localhost
welcome nginx
[root@bogon ~]# curl localhost
welcome nginx
可以看到容器内和宿主机curl结果一样
5.删除数据卷
在删除数据集之前要先关闭关联的容器,再删除数据卷
bash
[root@bogon ~]# docker stop nginx1 && docker rm nginx1
nginx1
nginx1
[root@bogon ~]# docker volume rm myvol
myvol
2.数据卷容器操作
1.宿主机上创建挂载目录
如果不提前创建,Docker 会自动创建
我这里不创建
2.将该目录作为就卷,创建容器
该容器不需要运行
bash
[root@bogon ~]# docker create --name voldata -v /data/nginx:/data nginx:latest
......
[root@bogon ~]# docker inspect voldata
"Mounts": [
{
"Type": "bind",
"Source": "/data/nginx",
"Destination": "/data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
......
3.挂载数据卷
在创建一个新容器后面跟参数:--volumes-from 卷容器名
其实和数据卷操作很像:
- 数据卷:直接挂载宿主机目录或匿名卷。
-数据卷容器 :一个专门用来共享卷的容器,其他容器通过
--volumes-from继承其卷。
bash
[root@bogon ~]# docker run --name nginx2 --volumes-from voldata -d nginx:latest
[root@bogon ~]# docker inspect nginx2
......
"Mounts": [
{
"Type": "bind",
"Source": "/data/nginx",
"Destination": "/data",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
......
检验数据是否相同(容器 和 主机挂载目录)
bash
1.#看最原始,应该是空
[root@bogon ~]# docker exec -it nginx2 sh
#
# ls /data/
[root@bogon ~]# ll -d /data/nginx
drwxr-xr-x. 2 root root 6 Apr 12 21:01 /data/nginx
[root@bogon ~]# ls /data/nginx
2.#在宿主机目录上加数据,检验容器对应目录是否同步
[root@bogon ~]# echo 1111 > /data/nginx/n1.txt
[root@bogon ~]# cat /data/nginx/n1.txt
1111
# cat /data/n1.txt
1111
3.#在容器里面改,看宿主机是否同步
# echo 2222 > /data/n1.txt
# cat /data/n1.txt
2222
[root@bogon ~]# cat /data/nginx/n1.txt
2222
4.添加新容器,用该卷容器
bash
[root@bogon ~]# docker run --name nginx3 -d --volumes-from voldata nginx:latest
[root@bogon ~]# docker exec -it nginx3 cat /data/n1.txt
2222#发现同步
2.#在新容器追加数据
# echo 3333 >> /data/n1.txt
# cat /data/n1.txt
2222
3333
#在容器nginx2中查看是否同步
# cat /data/n1.txt
2222
3333
#在宿主机查看
[root@bogon ~]# cat /data/nginx/n1.txt
2222
3333
从3,4可以看出,只要是创建时用了--volumes-from voldata,容器就和宿主机对应挂载目录数据一致。不论是在宿主机还是容器里面改动数据,都会同步。
宿主机对应挂载目录数据= '-v /data/nginx:/data' 前面部分。
3.绑定挂载
1.宿主机上创建挂载目录
bash
[root@bogon ~]# mkdir /bind_data
2.创建容器,并挂载目录
对比数据卷容器操作,不用先创建一个专门用于继承挂载的带卷容器,再挂载;
对比数据卷操作,不用先创建一个卷,再挂载,而是一般目录就可以挂载;
bash
[root@bogon ~]# docker run --name nginx4 -d -v /bind_data:/usr/share/nginx/html nginx:latest
3.查看主机目录 & 容器路径
bash
[root@bogon ~]# ls /bind_data/
[root@bogon ~]#
[root@bogon ~]# docker exec -it nginx4 sh
# ls /usr/share/nginx/html
#
两个都是空,因为/bind_data/为空,将其挂载到容器的/usr/share/nginx/html/目录,此目录也为空。
4.创建index.html
bash
[root@bogon ~]# echo here is nginx > /bind_data/index.html
[root@bogon ~]# cat /bind_data/index.html
here is nginx
5.在容器中确认
bash
# cat /usr/share/nginx/html/index.html
here is nginx
6.访问验证
bash
# curl localhost
here is nginx
[root@bogon ~]# curl localhost
curl: (7) Failed to connect to localhost port 80: Connection refused
宿主机失败情理之中,因为我们在创建容器时没有端口映射,从docker容器进程信息可以看到:
bash
[root@bogon ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
924b8718d549 nginx:latest "/docker-entrypoint...." 7 minutes ago Up 7 minutes 80/tcp nginx4
PORTS那一列没有映射,如果需要最好重新删除容器再创建。。。
但这里我们主要是验证 数据管理方式,能证明数据同步即可
4.临时挂载
与前面方法的关键区别:tmpfs 不像数据卷那样在宿主机有实际路径
它只在内存中存在,不占用磁盘空间
1.创建容器
这里的目录是容器内部目录!!!
bash
[root@bogon ~]# docker run -d -it --name nginx5 --tmpfs /tmpfs_data nginx:latest
这个命令的含义是:
- 在容器内部 创建一个目录
/tmpfs_data- 将这个目录挂载为 tmpfs 类型(存储在内存中)
- 容器内的进程可以读写这个目录
2.查看相关信息
bash
[root@bogon ~]# docker container inspect nginx5
......
"Tmpfs": {
"/tmpfs_data": ""
},
......
3.验证
bash
[root@bogon ~]# docker exec -it nginx5 bash
root@9bee0eb1edea:/# df -h /tmpfs_data
Filesystem Size Used Avail Use% Mounted on
tmpfs 3.8G 0 3.8G 0% /tmpfs_data
root@9bee0eb1edea:/# echo 'test data' > /tmpfs_data/test.txt
root@9bee0eb1edea:/# cat /tmpfs_data/test.txt
test data
root@9bee0eb1edea:/# exit
exit
[root@bogon ~]# docker restart nginx5
nginx5
[root@bogon ~]# docker exec nginx5 ls /tmpfs_data/
[root@bogon ~]#
可以看到会话中断则没有数据了,是临时的,在内存中
5.四种方式对比总结
好的,下面按照你列出的四种分类,从原理、作用、场景三个维度进行简要介绍。
1. 数据卷管理 (Volumes)
原理
- Docker 在宿主机上创建一个由 Docker 守护进程管理的目录(默认在
/var/lib/docker/volumes/) - 容器通过指定卷名或自动创建匿名卷,挂载该目录
作用
- 持久化存储数据,独立于容器生命周期
- 多个容器可共享同一个卷
- 支持卷驱动(如 NFS、云存储等)
典型场景
- 数据库数据存储(MySQL、PostgreSQL)
- 应用需要保留的配置文件、上传文件
- 生产环境中的大多数持久化需求
2. 数据卷容器管理 (Data Volume Container)
原理
- 创建一个专门的空容器,该容器内部定义了一个或多个数据卷(通过
VOLUME指令或-v) - 其他容器通过
--volumes-from继承该容器的卷挂载
作用
- 在 Docker 早期版本中,用于在容器间共享和传递数据卷
- 作为"数据卷的代理"来管理卷的生命周期
典型场景(历史)
- 多个 Web 容器共享一个公共代码卷
- 数据备份容器与业务容器共享卷
现状 :命名卷已经完美替代了卷容器的所有功能,不再需要学习和使用。
3. 绑定挂载 (Bind Mounts)
原理
- 直接将宿主机上的任意绝对路径 (如
/home/user/data)挂载到容器内 - 不经过 Docker 管理,Docker 只负责建立映射关系
作用
- 让容器直接访问宿主机文件系统
- 宿主机修改实时反映到容器内(反之亦然)
典型场景
- 开发环境:代码目录挂载,修改代码容器内热更新
- 配置注入 :将宿主机上的
nginx.conf、config.yml挂载到容器 - 访问宿主机特殊文件 :如
/var/run/docker.sock
4. 临时挂载 (tmpfs Mounts)
原理
- 挂载到容器的内存中,而非磁盘
- 容器停止/删除后,数据彻底丢失
- 受宿主机内存限制
作用
- 极快读写速度(内存速度)
- 不落盘:敏感数据不会写入磁盘,降低泄露风险
- 容器内临时空间不影响宿主机磁盘
典型场景
- 敏感信息:临时存储 OAuth token、密钥(容器重启即消失)
- 高频写入临时数据:缓存、临时计算结果、会话数据
- 日志缓冲:高频日志先写入 tmpfs 再定期刷盘,减少磁盘 I/O
- 性能测试:需要极致 I/O 性能且数据可丢失的场景
一句话总结对比表
| 方式 | 数据位置 | 持久性 | 主要场景 | 推荐度 |
|---|---|---|---|---|
| 数据卷管理 | Docker管理目录 | ✅ 持久 | 生产环境持久数据 | ⭐⭐⭐⭐⭐ |
| 数据卷容器 | Docker管理目录 | ✅ 持久 | 已过时,不推荐 | ❌ 废弃 |
| 绑定挂载 | 宿主机任意路径 | ✅ 持久 | 开发、配置注入 | ⭐⭐⭐⭐ |
| 临时挂载 | 内存 | ❌ 不持久 | 临时/敏感/高速数据 | ⭐⭐ |
6.数据还原备份
有多种方法,比如:
1.--volumes-from 方式
- 直接挂载 Volume 方式(volume 独立存在)
- Bind Mount 主机目录方式
- Docker cp 方式(小文件或临时)
但是最常用、最好用的是:--volumes-from + tar 方式
因此就重点掌握这个方法即可
6.1 创建宿主机源文件
bash
[root@bogon ~]# mkdir -p /root/data
[root@bogon ~]# ls /root/data/
[root@bogon ~]#
[root@bogon ~]# echo here is nginx > /root/data/index.html
6.2 创建卷容器(建立映射关系)
主机目录可以不单独创建,容器创建时自动创建;
且卷容器不需要启动;
bash
[root@bogon ~]# docker create --name nginxdata -v /root/data:/usr/share/nginx/html nginx:latest
[root@bogon ~]# docker inspect nginxdata
。。。
"Mounts": [
{
"Type": "bind",
"Source": "/root/data",
"Destination": "/usr/share/nginx/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
。。。
作用 :创建名为
nginxdata的容器,并建立宿主机目录 到容器目录的映射:text
宿主机 容器 nginxdata /root/data/index.html ←→ /usr/share/nginx/html/index.html关键 :此时虽然容器没启动,但映射关系已建立,数据已经"连接"上了。
6.3 备份(读取映射的数据)
bash
[root@bogon ~]# docker run --rm --volumes-from nginxdata -v /root/backup:/backup nginx:latest tar -zcf /backup/nginx_data.tar.gz /usr/share/nginx/html/
创建容器中--rm,在容器内部执行完tar -zcf /backup/nginx_data.tar.gz /usr/share/nginx/html/后,退出容器并停止,停止后自动删除。
所以该容器不再存在,不用手动删除去模拟数据破坏
bash[root@bogon ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4ea8129ac2e4 nginx:latest "/docker-entrypoint...." 9 minutes ago Created nginxdata可以看到没有刚刚创建的临时容器(因为
--rm自动删除了),但卷容器nginxdata和备份文件都在,数据安全。
Q 关于我自己写的index.html是怎么被打包进去的?
执行过程分解:
1. 临时容器启动,通过 --volumes-from nginxdata 获得映射关系
2. 临时容器内的 /usr/share/nginx/html/ 实际指向宿主机的 /root/data/
3. tar 命令读取 /usr/share/nginx/html/index.html
↓ 实际读取的是宿主机 /root/data/index.html
↓ 内容:"here is nginx"
4. tar 打包后,通过 -v /root/backup:/backup 写入宿主机 /root/backup/nginx_data.tar.gz
数据流向图:
宿主机 /root/data/index.html
↓ (通过 bind mount 映射)
容器 nginxdata 的 /usr/share/nginx/html/index.html
↓ (通过 --volumes-from 继承)
临时容器的 /usr/share/nginx/html/index.html
↓ (tar 读取并打包)
临时容器的 /backup/nginx_data.tar.gz
↓ (通过 -v 挂载)
宿主机 /root/backup/nginx_data.tar.gz
6.4 检查数据备份
bash
#查看宿主机上
[root@bogon ~]# ls /root/backup/
nginx_data.tar.gz
[root@bogon ~]# tar -tf /root/backup/nginx_data.tar.gz
usr/share/nginx/html/
usr/share/nginx/html/index.html
6.5 还原
bash
[root@bogon ~]# docker run --name n1 --volumes-from nginxdata -v /root/backup:/backup nginx:latest sh -c "tar -zxf /backup/nginx_data.tar.gz -C / && ll /usr/share/nginx/html/ && cat /usr/share/nginx/html/index.html"
total 4
-rw-r--r--. 1 root root 14 Apr 13 10:51 index.html
here is nginx
可以看出容器n1里面有解压好的文件。。。证明把备份到卷容器里面的压缩包成功解压出来了
6.5 数据来源总结
nginxdata 卷容器作为数据中转站 :备份时,临时容器通过 --volumes-from nginxdata 读取 /usr/share/nginx/html/ 的数据**(此时该目录下的所有文件已经是宿主机上自定义的文件)**,打包存到宿主机;还原时,容器 n1 通过 --volumes-from nginxdata 将 tar 包解压回 /usr/share/nginx/html/,实现数据恢复。
7.知识点追加
Q: 创建容器后还可以加映射端口吗?
1.删除并重建容器,这是最保险通用的方法
2.使用软件socat 或者 iptables
- socat :一个强大的网络瑞士军刀软件,可以在不同协议之间转发数据,用来做端口映射只是它的功能之一。
- iptables :Linux系统的防火墙配置工具软件,通过修改内核的网络规则来实现端口转发。
socat iptables 性质 独立的用户态程序 Linux内核内置的防火墙工具 安装 需要手动安装 系统自带(无需安装) 位置 应用层 内核层
推荐:重建容器(特别是正式生产环境 / 企业中)
Docker 设计时就把端口映射作为容器创建时的参数,不是运行时修改的配置。强行用其他手段属于"绕路走"。
具体对比
| 方面 | 重建容器 | socat/iptables 转发 |
|---|---|---|
| 数据持久性 | 数据卷不受影响,配置会丢失 | 容器内数据完整保留 |
| 可管理性 | docker ps 直接看到端口 |
看不到,忘了就忘了 |
| 稳定性 | Docker 原生管理,重启自动恢复 | 重启需重新配置 |
| 性能 | 无损耗 | 轻微损耗(socat 更明显) |
| 可维护性 | 新人一看就懂 | 需要额外排查转发层 |
测试环境可以试一下,反正就是玩一下。这里不介绍了,不是本篇文章重点。。。重点是掌握docker的数据管理