Docker 数据持久化:4种挂载方式 + 备份还原实战

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.创建容器,并挂载目录

  1. 对比数据卷容器操作,不用先创建一个专门用于继承挂载的带卷容器,再挂载;

  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.confconfig.yml 挂载到容器
  • 访问宿主机特殊文件 :如 /var/run/docker.sock

4. 临时挂载 (tmpfs Mounts)

原理

  • 挂载到容器的内存中,而非磁盘
  • 容器停止/删除后,数据彻底丢失
  • 受宿主机内存限制

作用

  • 极快读写速度(内存速度)
  • 不落盘:敏感数据不会写入磁盘,降低泄露风险
  • 容器内临时空间不影响宿主机磁盘

典型场景

  • 敏感信息:临时存储 OAuth token、密钥(容器重启即消失)
  • 高频写入临时数据:缓存、临时计算结果、会话数据
  • 日志缓冲:高频日志先写入 tmpfs 再定期刷盘,减少磁盘 I/O
  • 性能测试:需要极致 I/O 性能且数据可丢失的场景

一句话总结对比表

方式 数据位置 持久性 主要场景 推荐度
数据卷管理 Docker管理目录 ✅ 持久 生产环境持久数据 ⭐⭐⭐⭐⭐
数据卷容器 Docker管理目录 ✅ 持久 已过时,不推荐 ❌ 废弃
绑定挂载 宿主机任意路径 ✅ 持久 开发、配置注入 ⭐⭐⭐⭐
临时挂载 内存 ❌ 不持久 临时/敏感/高速数据 ⭐⭐

6.数据还原备份

有多种方法,比如:

1.--volumes-from 方式

  1. 直接挂载 Volume 方式(volume 独立存在)
  2. Bind Mount 主机目录方式
  3. 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的数据管理

相关推荐
弹简特1 小时前
【Linux命令饲养指南】03-Linux文件操作与编辑:从“摸鱼”到“搬砖”,这篇让你把文件玩出花
linux
LSG_Dawn2 小时前
linux 开机黑屏,/dev/nvme1n1p4:clean, xxxxx/xxxxxxx files, xxxx/xxxx blocks
linux·运维·服务器
蜜獾云2 小时前
Nginx-包教包会-入门
运维·nginx
喜欢吃燃面2 小时前
Linux 进程间通信:命名管道与 System V 共享内存深度解析
linux·运维·服务器·学习
springlustre2 小时前
阿里云CentOS上使用Docker部署OpenClaw并接入百炼大模型
docker·centos·openclaw
有谁看见我的剑了?2 小时前
关于linux namespace学习
linux·运维·docker
顾喵2 小时前
ARM处理器体系结构
linux·arm
特长腿特长2 小时前
systemd 服务配置文件,xxx.service 编辑指南,自定义我们自己的服务。
linux·网络·云原生
ai产品老杨2 小时前
异构计算时代的安防底座:基于 Docker 的 X86/ARM 双模部署与 NPU 资源池化实战
arm开发·docker·容器