当前位置: 首页 > news >正文

五、Docker 核心技术:容器数据持久化之数据卷

Docker 容器本身是无状态且生命周期短暂的。当一个容器被删除时,它在可写层产生的所有数据都会随之消失。这对于需要持久化存储数据的应用 (如数据库、日志系统、用户上传内容) 来说是不可接受的。为了解决这个问题,Docker 提供了多种数据持久化方案,其中最重要、最推荐的就是数据卷

一、什么是容器数据卷

数据卷宿主机文件系统中一个特殊的目录,它由 Docker 管理 (/var/lib/docker/volumes/ 目录下),并可以直接映射一个或多个容器的指定目录下。

数据卷的核心优势:

数据持久化:数据卷的生命周期独立于任何容器。即使所有使用该数据卷的容器都被删除,数据卷及其中的数据依然存在
数据共享多个容器可以同时挂载同一个数据卷,从而实现容器间的数据共享和同步
高性能:数据卷绕过了容器的联合文件系统 (UnionFS),直接读写宿主机的文件系统,具有接近原生的I/O性能。
易于管理:Docker 提供了专门的命令 (docker volume ...) 来创建、查看、删除数据卷,便于备份、迁移和恢复

二、数据卷的使用

创建或运行容器时,我们主要使用 -v--mount 标志来挂载数据卷-v 语法更简洁--mount 语法更明确推荐在生产环境和复杂场景下使用 --mount

1. 匿名挂载

如果你在 -v 标志中只指定容器内的路径,Docker 会自动创建一个匿名的数据卷,并将其挂载到该路径。

语法:

-v /path/in/container

代码案例:

docker run -d -P --name nginx-anon -v /usr/share/nginx/html nginx
  • 这个命令会创建一个新的、名字是随机哈希值的数据卷,并挂载到容器的 /usr/share/nginx/html 目录。
  • 我们可以通过 docker inspect 查看这个匿名数据卷具体信息
docker inspect nginx-anon

在这里插入图片描述

在输出的 "Mounts" 部分,你会看到类似这样的信息:

"Mounts": [{"Type": "volume","Name": "a1b2c3d4...", // 随机生成的长哈希值"Source": "/var/lib/docker/volumes/a1b2c3d4.../_data","Destination": "/usr/share/nginx/html",...}
]

在这里插入图片描述

  • 缺点:匿名挂载的数据卷名称不直观,难以管理和复用

2.具名挂载

这是最推荐的数据卷使用方式。你可以为数据卷指定一个有意义的名称,方便后续的引用、共享和管理

语法:

-v 方式: volume-name:/path/in/container
--mount 方式: type=volume,source=volume-name,target=/path/in/container

代码案例:

步骤一:创建具名数据卷 (可选,Docker会在挂载时自动创建)

docker volume create my-nginx-data

步骤二:使用具名数据卷运行容器

  • 使用 -v 标志:
docker run -d -P --name nginx-named-v -v my-nginx-data:/usr/share/nginx/html nginx
  • 使用 --mount 标志 (推荐):
docker run -d -P --name nginx-named-mount --mount type=volume,source=my-nginx-data,target=/usr/share/nginx/html nginx
  • 在这两个例子中,名为 my-nginx-data数据卷挂载到了容器的 /usr/share/nginx/html 目录。
  • 现在,你可以删除并重建 nginx-named-vnginx-named-mount 容器,但只要重新挂载 my-nginx-data 数据卷,网站的数据 (如 index.html) 就会保持不变

数据卷管理命令:

# 列出所有数据卷
docker volume ls# 查看某个数据卷的详细信息
docker volume inspect my-nginx-data# 删除一个数据卷 (前提是没有容器正在使用它)
docker volume rm my-nginx-data# 删除所有不再被任何容器使用的悬空数据卷 (dangling volumes)
docker volume prune

在这里插入图片描述
在这里插入图片描述

3. 数据卷 vs 绑定挂载

除了由 Docker 管理的数据卷,Docker 还支持另一种强大的挂载方式——绑定挂载。它允许我们将宿主机上任意的一个文件或目录直接映射到容器中。

绑定挂载语法 (使用 -v):

-v /path/on/host:/path/in/container

与数据卷的核心区别及选择:

特性数据卷绑定挂载
管理方由 Docker 管理,位于 Docker 的专用存储区域 (/var/lib/docker/volumes/)。由用户管理,可以是宿主机文件系统中的任意路径
可移植性。数据卷的定义与宿主机的目录结构无关,便于在不同环境中迁移。。依赖于宿主机上特定的目录结构,不易迁移。
性能在 Linux 上通常性能更高,因为它为数据I/O进行了优化。性能也很好,但可能受宿主机文件系统权限等因素影响。
权限Docker 自动处理权限。可能存在宿主机与容器内用户权限不匹配的问题。
适用场景推荐用于生产环境和所有需要持久化应用数据的场景,如数据库文件、应用日志等。适用于开发环境,如将源代码目录挂载到容器中进行实时代码调试;或共享宿主机配置文件到容器。

代码示例:直观感受数据卷与绑定挂载的行为差异

这个示例将清晰地展示数据卷独立于容器生命周期的特性,以及绑定挂载下宿主机与容器实时同步

场景一:使用数据卷的持久性演示

  1. 运行一个容器,使用具名数据卷并写入数据:
docker run -d --name vol-test-container -v my-persistent-data:/data ubuntu sleep infinity
docker exec vol-test-container sh -c "echo 'This data is in a volume' > /data/message.txt"

在这里插入图片描述

  • 此时,名为 my-persistent-data 的数据卷中已经包含了 message.txt 文件。
  1. 在容器内删除文件,验证宿主机数据卷不受影响:(为模拟容器内误操作)
docker exec vol-test-container rm /data/message.txt

验证容器内文件已删除

docker exec vol-test-container ls /data

在这里插入图片描述

(此时应无输出)

关键点:此时 my-persistent-data 这个数据卷本身在宿主机上仍然包含 message.txt 文件。容器的删除操作仅仅是在容器的可写层记录了“该文件已删除”的标记并未真正删除数据卷中的源文件。

  1. 删除容器,然后创建一个新容器挂载同一个数据卷:
docker stop vol-test-container
docker rm vol-test-container# 创建一个全新的容器,挂载之前的数据卷
docker run --name vol-test-checker -it -v my-persistent-data:/data ubuntu
  1. 在新容器中查看数据:
    当你进入 vol-test-checker 容器的交互式终端后,查看 /data 目录:
# 在 vol-test-checker 容器的shell中执行
ls /data
# 输出应为:message.txtcat /data/message.txt
# 输出应为:This data is in a volume

结论:这个实验有力地证明了,数据卷中的数据是独立且持久的。即使容器内的文件被看似“删除”,或者整个容器删除,数据卷中的原始数据安然无恙,可以被新的容器重新挂载和使用。

场景二:使用绑定挂载的实时同步演示

  1. 在宿主机上创建一个目录和文件:
mkdir -p ./host-data
echo "Initial data from host" > ./host-data/sync.txt
  1. 运行一个容器,将宿主机目录绑定挂载到容器中:
docker run -d --name bind-test-container -v $(pwd)/host-data:/data ubuntu tail -f /dev/null
  • tail -f /dev/null 是一个让容器保持运行的技巧。
  • 现在,宿主机的 ./host-data 目录与容器的 /data 目录实时同步

在这里插入图片描述
3. 验证容器内可以看到宿主机文件:

docker exec bind-test-container cat /data/sync.txt
# 输出应为:Initial data from host

在这里插入图片描述
4. 宿主机上修改文件内容:

echo "Host updated the file" >> ./host-data/sync.txt
  1. 容器内立即查看变化:
docker exec bind-test-container cat /data/sync.txt
# 输出现在应包含两行:
# Initial data from host
# Host updated the file

在这里插入图片描述

  1. 容器内删除文件:
docker exec bind-test-container rm /data/sync.txt
  1. 宿主机上验证文件是否也被删除:
ls ./host-data/
# (此时应无输出,文件已被删除)

在这里插入图片描述

结论:绑定挂载建立了宿主机和容器之间文件系统的直接链接。任何一方对挂载目录中内容的修改或删除,都会立即、真实地反映在另一方。这种实时同步的特性使其非常适合开发时共享源代码

4. 综合案例:使用具名数据卷持久化 MySQL 数据

这个案例将演示如何创建一个 MySQL 容器,并将其数据目录 /var/lib/mysql 持久化到一个具名数据卷中,从而实现数据库数据的安全存储

步骤一:创建具名数据卷
为了清晰管理,我们先创建一个名为 mysql-data 的数据卷。

docker volume create mysql-data

步骤二:运行 MySQL 容器并挂载数据卷
我们将运行一个 MySQL 8.0 容器,并设置 root 密码

docker run -d \
--name my-mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
--mount type=volume,source=mysql-data,target=/var/lib/mysql \
mysql:8.0
  • -d: 后台运行容器。
  • --name my-mysql: 为容器命名。
  • -p 3306:3306: 将宿主机的 3306 端口映射到容器的 3306 端口。
  • -e MYSQL_ROOT_PASSWORD=...: 通过环境变量设置 MySQL 的 root 用户密码。
  • --mount ...: 核心部分。将我们创建的 mysql-data 数据卷挂载到容器内部存放数据库文件标准路径 /var/lib/mysql

步骤三:验证数据持久化

  1. 进入容器并创建数据
    使用 docker exec 进入正在运行的 MySQL 容器,并登录到数据库。
docker exec -it my-mysql mysql -uroot -pmysecretpassword

在 MySQL 命令行中,创建一个新的数据库和表,并插入一些数据

CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50));
INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob');
EXIT;

在这里插入图片描述
主机也能正常连接上
在这里插入图片描述

  1. 删除容器
    现在,我们模拟一次容器故障或升级删除这个 MySQL 容器。
docker stop my-mysql
docker rm my-mysql

此时,容器已经不存在了。

  1. 重新创建容器,挂载同一个数据卷
    我们再次运行一个 MySQL 容器,使用相同的命令,确保它挂载的还是 mysql-data 这个数据卷。
docker run -d \
--name my-mysql-new \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=mysecretpassword \
--mount type=volume,source=mysql-data,target=/var/lib/mysql \
mysql:5.7
  1. 验证数据是否恢复
    等待新容器 my-mysql-new 完全启动后,再次进入这个新容器。
docker exec -it my-mysql-new mysql -uroot -pmysecretpassword

在 MySQL 命令行中,检查我们之前创建的数据库和数据是否存在。

USE testdb;
SELECT * FROM users;

你会看到输出

+----+-------+
| id | name  |
+----+-------+
|  1 | Alice |
|  2 | Bob   |
+----+-------+

证明了,即使容器被删除存储在数据卷中的数据被完美地保留了下来,并在新容器得以恢复

总结: 容器数据卷是实现Docker数据持久化首选方案。通过使用具名数据卷,我们可以安全地存储应用数据解耦数据与容器的生命周期,并轻松实现数据的共享、备份和恢复,为在生产环境运行有状态应用提供了坚实的基础


练习题

题目一:创建与查看数据卷
写出一条命令,创建一个名为 app-config 的具名数据卷,然后写出另一条命令来查看这个数据卷的详细信息。

题目二:匿名挂载
写出一条命令,以后台模式运行一个 ubuntu 容器,并为容器内的 /data 目录进行匿名挂载。

题目三:具名挂载 (使用 -v)
写出一条命令,以后台模式运行一个名为 my-redisredis 容器,并使用 -v 标志将一个名为 redis-data 的具名数据卷挂载到容器的 /data 目录。

题目四:具名挂载 (使用 --mount)
使用 --mount 标志重写上一题的命令,实现完全相同的效果。

题目五:绑定挂载
写出一条命令,运行一个临时的、交互式的 alpine 容器,并将宿主机当前目录下的 app 子目录 (假设为 ./app) 绑定挂载到容器的 /app 目录。容器启动后执行 ls /app 命令。

题目六:数据共享

  1. 首先,运行一个名为 writer-containerbusybox 容器,将一个名为 shared-volume 的数据卷挂载到 /shared。容器启动后,向 /shared/message.txt 文件写入 “Hello from writer”。
  2. 然后,运行另一个名为 reader-containerbusybox 容器,同样挂载 shared-volume 数据卷到 /shared,并读取 /shared/message.txt 文件的内容。
    (请分别写出这两个 docker run 命令)

题目七:数据卷清理
写出一条命令,可以一次性删除所有当前未被任何容器使用的Docker数据卷。

题目八:数据卷数据备份
假设 mysql-data 数据卷中包含了重要的数据库文件,你希望对其进行备份。请描述一种简单的、利用另一个临时容器来备份该数据卷中所有文件到宿主机 /backup 目录的思路或命令。

答案与解析

答案一:
创建数据卷:

docker volume create app-config

查看详细信息:

docker volume inspect app-config

解析: docker volume create 用于创建具名数据卷,docker volume inspect 用于查看其元数据,包括在宿主机上的实际存储路径。

答案二:

docker run -d --name ubuntu-anon -v /data ubuntu

解析: -v 标志后只跟了容器内的路径 /data,这会触发Docker创建一个匿名数据卷并挂载到此路径。

答案三:

docker run -d --name my-redis -v redis-data:/data redis

解析: -v 标志使用 [volume_name]:[container_path] 的格式来进行具名挂载。如果 redis-data 数据卷不存在,Docker会自动创建它。

答案四:

docker run -d --name my-redis --mount type=volume,source=redis-data,target=/data redis

解析: --mount 标志使用更明确的键值对语法。type=volume 指定类型,source 指定数据卷名称,target 指定容器内路径。

答案五:

docker run --rm -it --mount type=bind,source=$(pwd)/app,target=/app alpine ls /app

解析: --mount type=bind 指定了绑定挂载。source=$(pwd)/app 表示宿主机当前工作目录下的 app 目录。--rm 使容器退出后自动删除,-it 提供交互式终端。容器启动后直接执行 ls /app 命令。

答案六:

  1. 运行 writer-container
docker run --name writer-container -v shared-volume:/shared busybox sh -c "echo 'Hello from writer' > /shared/message.txt"
  1. 运行 reader-container
docker run --name reader-container -v shared-volume:/shared busybox cat /shared/message.txt

解析: 两个容器都挂载了同一个具名数据卷 shared-volume。第一个容器向卷中写入文件,第二个容器可以立即读取到这个文件,实现了数据共享。

答案七:

docker volume prune

解析: docker volume prune 是一个方便的命令,用于清理不再被任何(包括已停止的)容器引用的数据卷,可以释放磁盘空间。

答案八:

docker run --rm \
--mount type=volume,source=mysql-data,target=/dbdata,readonly \
--mount type=bind,source=/backup,target=/backup_host \
ubuntu \
tar czvf /backup_host/mysql-backup-$(date +%Y%m%d).tar.gz -C /dbdata .

在这里插入图片描述

日期:2025年9月5日
专栏:Docker教程


文章转载自:

http://ND1AyrSv.wgqtj.cn
http://f2N5id1V.wgqtj.cn
http://XLzdPwix.wgqtj.cn
http://3kKmIU1u.wgqtj.cn
http://zWMIqmqs.wgqtj.cn
http://QBZP7ZZC.wgqtj.cn
http://Sg6PbFrR.wgqtj.cn
http://vJDRjqga.wgqtj.cn
http://4xC6IeKK.wgqtj.cn
http://yJ82LNAm.wgqtj.cn
http://uPyKfU8Q.wgqtj.cn
http://FCwL8y2q.wgqtj.cn
http://MXu124Qd.wgqtj.cn
http://MCLOTu96.wgqtj.cn
http://9sO7QcXL.wgqtj.cn
http://J7aJrp4b.wgqtj.cn
http://myTiVTru.wgqtj.cn
http://rL5b45XT.wgqtj.cn
http://OJnGQ110.wgqtj.cn
http://wsDVPn6r.wgqtj.cn
http://V1wkE4g0.wgqtj.cn
http://E3qPhTUk.wgqtj.cn
http://3aVVGIk1.wgqtj.cn
http://2xdzihgB.wgqtj.cn
http://9KTAVvz6.wgqtj.cn
http://p7XVzRcV.wgqtj.cn
http://gCKRYQYH.wgqtj.cn
http://D1dQ3WJr.wgqtj.cn
http://KJxP91GY.wgqtj.cn
http://jc048XBJ.wgqtj.cn
http://www.dtcms.com/a/368101.html

相关文章:

  • (计算机网络)DNS解析流程及两种途径
  • 3-8〔OSCP ◈ 研记〕❘ WEB应用攻击▸REST API枚举
  • Tabby使用sftp上传文件服务器ssh一直断开
  • 解密大语言模型推理:输入处理背后的数学与工程实践
  • python 自动化在web领域应用
  • FDTD_3 d mie_仿真
  • Electron 安全性最佳实践:防范常见漏洞
  • SAP ERP公有云详解:各版本功能对比与选型
  • Linux:进程信号理解
  • 深度学习:Dropout 技术
  • Linux 磁盘扩容及分区相关操作实践
  • 【前端】使用Vercel部署前端项目,api转发到后端服务器
  • 【ARDUINO】ESP8266的AT指令返回内容集合
  • Netty从0到1系列之Netty整体架构、入门程序
  • 实战记录:H3C路由器IS-IS Level-1邻居建立与路由发布
  • iOS 抓包工具有哪些?常见问题与对应解决方案
  • 【Linux】网络安全管理:SELinux 和 防火墙联合使用 | Redhat
  • Boost搜索引擎 网络库与前端(4)
  • 服务器硬盘“Unconfigured Bad“状态解决方案
  • 警惕!你和ChatGPT的对话,可能正在制造分布式妄想
  • 中天互联:AI 重塑制造,解锁智能生产新效能​
  • 如何制造一个AI Agent:从“人工智障”到“人工智能”的奇幻漂流
  • 鼓励员工提出建议,激发参与感——制造企业软件应用升级的密钥
  • 2025世界职校技能大赛总决赛争夺赛汽车制造与维修赛道比赛资讯
  • LeetCode 240: 搜索二维矩阵 II - 算法详解(秒懂系列
  • [特殊字符] AI时代依然不可或缺:精通后端开发的10个GitHub宝藏仓库
  • 【MFC】对话框节点属性:Condition(条件)
  • 【MFC 小白日记】对话框编辑器里“原型图像”到底要不要勾?3 分钟看懂!
  • 【为YOLOv11Seg添加MFC界面】详细指南
  • VBA 中使用 ADODB 操作 SQLite 插入中文乱码问题