Skip to content
60.Docker»60.CNB下的Docker应用»LV030-存储管理.md

LV030-存储管理

一、为什么容器需要持久化存储

容器文件系统的本质是在镜像层上面创建的读写层,运行中的容器对任何文件的修改都存在于该读写层,当容器被删除时,容器中的读写层也会随之消失。

二、volume——数据卷

1. 什么是卷?

在 Docker 的世界里,卷(Volumes)可是实现文件共享与持久化存储的 “神器”。简单来说,卷就是一个 特殊的目录,它专门用于绕过容器的常规文件系统,在容器与宿主机之间搭建起一座稳固的数据桥梁。与容器内部普通的目录相比,卷有着本质的区别。容器内普通目录的数据通常是临时存储的,一旦容器停止或被删除,这些数据就如同泡沫般消散;而卷中的数据却能稳稳扎根于宿主机的文件系统,独立于容器的生命周期,始终保持完好无损。

想象一下,我们在容器里运行一个数据库应用,容器内的数据库文件存储在普通目录下,哪天不小心容器崩溃或者需要重新部署,辛辛苦苦录入的数据瞬间化为乌有,这场景简直是 “灾难现场”。但要是使用卷来存储数据库文件,无论容器怎么折腾,数据都安然无恙地躺在宿主机上,随时等待容器重新挂载使用。

2. 接本原理

Docker 卷的实现原理是在主机的 /var/lib/docker/volumes 目录下,根据卷的名称创建相应的目录,然后在每个卷的目录下创建 _data 目录,在容器启动时如果使用 --mount 参数,Docker 会把主机上的目录直接映射到容器的指定目录下,实现数据持久化。

其实卷的本质是文件或者目录,只是它可以绕过默认的联合文件系统,直接以文件或目录的形式存在于宿主机上。卷的概念不仅解决了数据持久化的问题,还解决了容器间共享数据的问题。使用卷可以将容器内的目录或文件持久化,当容器重启后保证数据不丢失。

3. 有什么优势?

(1)卷具有强大的数据持久化能力。正如前文所提到的,容器内应用产生的数据若存储在卷中,即便容器遭遇关停、删除等变故,数据依旧毫发无损地存于宿主机,这为那些需要长期保存数据的应用,如数据库、日志存储等,提供了坚实可靠的后盾。以 MySQL 数据库容器为例,将数据库文件存放于卷内,无论是日常的容器重启优化,还是紧急情况下的容器重建,数据都能无缝衔接,业务连续性得以保障,有效避免因数据丢失带来的巨大损失。

(2)共享便捷。多个容器可以同时挂载同一个卷,瞬间实现数据的互联互通。在一个微服务架构的电商应用里,前端容器、后端 API 容器以及订单处理容器等,可能都需要共享同一份商品配置信息、用户认证密钥等关键数据,通过卷挂载,这些容器就能像共享 “公共资源库” 一样,轻松获取所需数据,极大地简化了容器间的协作流程,提升整体运行效率。

(3)卷独立于容器生命周期这一特性,赋予了开发与运维工作极大的灵活性。开发阶段,开发人员可以随意启停、修改容器,不用担心数据丢失,随时切换不同版本的应用进行测试;运维人员在进行容器迁移、集群扩展等操作时,也无需顾虑数据迁移的繁琐与风险,只需确保卷的正确挂载,就能快速完成任务。

4. 基本命令

4.1 创建数据卷

shell
docker volume create <volume-name>

【例】

shell
docker volume create nginx-vol

4.2 列出所有卷

shell
docker volume ls

4.3 查看卷信息

docker volume inspect 命令可获取挂载路径、驱动类型等元数据。

shell
docker volume inspect <volume-name>

【例】

shell
docker volume inspect nginx-vol

4.4 挂载到容器

shell
docker run -d --mount src=volume-name,dst=container_dir image
docker run -d -v volume-name:container_dir image

【例】

shell
docker run -d --name=nginx-test1 --mount src=nginx-vol,dst=/usr/share/nginx/html nginx
docker run -d --name=nginx-test2 -v nginx-vol:/usr/share/nginx/html nginx

4.5 查看是否被使用

shell
docker ps -a --filter volume=volume-name

4.6 删除数据卷

  • 删除指定数据卷
bash
docker volume rm <volume_name>
  • 删除未使用的卷
bash
docker volume prune

5. 使用示例

5.1 创建一个数据卷

bash
docker volume create test-vol  # 创建一个自定义容器卷
docker volume ls               # 查看所有容器卷
docker volume inspect test-vol # 查看指定容器卷详情信息

【例】

shell
  /workspace git:(main)  docker volume create test-vol  # 创建一个自定义容器卷
test-vol
  /workspace git:(main)  docker volume ls               # 查看所有容器卷
DRIVER    VOLUME NAME
local     test-vol
  /workspace git:(main)  
  /workspace git:(main)  docker volume inspect test-vol # 查看指定容器卷详情信息
[
    {
        "CreatedAt": "2025-11-01T07:35:25Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/test-vol/_data",
        "Name": "test-vol",
        "Options": null,
        "Scope": "local"
    }
]

volumes:默认位于 /var/lib/docker/volumes 目录中。/var/lib/docker/volumes/test-vol/_data 这整个路径都需要 root 用户才有权限访问,而 cnb 中,我们并不具备这个权限所以这里就没有办法访问,但是要是在 windows 主机或者 linux 主机上装了 docker 再进行操作的话就没问题了。

5.2 使用数据卷

5.2.1 挂载并创建文件
bash
# 方式 1:--mount
# docker run -d --name my_container -v my_volume:/path/in/container my_image
docker run -it --name=my_container -p 8000:8000 --mount src=test-vol,dst=/usr/share/my-vol-data sumumm/docker-demo:1.0.0 /bin/bash

# 方式 2; -v
# docker run -d --name my_container --mount src = my_volume, dst =/path/in/container my_image
docker run -it --name=my_container -p 8000:8000 -v test-vol:/usr/share/my-vol-data sumumm/docker-demo:1.0.0 /bin/bash

无论是使用 -v 还是 --mount 选项,都可以将 Docker 卷挂载到容器中。挂载后,容器就可以读写卷中的数据,实现了数据在容器之间的共享和持久化存储。我们可以使用下面的命令来查看是否有容器使用使用了 test-vol 卷:

bash
docker ps -a --filter volume=test-vol

然后我们在容器中往这个数据卷中写入文件:

bash
cd /usr/share/my-vol-data/
echo "my-vol-data" > README.md
5.2.2 宿主机访问数据卷

但是我在宿主机中访问的时候报错了,好像没有这个目录以及文件:

image-20251101154111824

这里其实已经告诉我们了,没有权限,因为这是 cnb 的云原生开发环境,所以我们没有 root 用户权限。后来我去 VMware 中的安装的 Ubuntu 系统也尝试了一下:

image-20251018101732010

加上 sudo 权限后就可以了。

5.2.3 其他容器访问

其实我们还可以再创建一个容器,挂载这个卷,就可以看到这个文件和内容了:

shell
docker run -it --name=my_container2 -v test-vol:/usr/share/my-vol-data sumumm/docker-demo:1.0.0 /bin/bash

image-20251101154435084

三、Bind Mount 挂载

1. 简介

BindMount 直接将主机目录直接挂载到容器,适合开发调试场景,可直接修改主机文件并实时生效。

2. 基本命令

shell
# 方法 1:-v 参数(推荐)
docker run -v host_dir:container_dir image

# 方法 2:--mount 参数
docker run --mount type=bind,src=host_dir,dst=container_dir image

【例】

shell
# 方法 1:-v 参数(推荐)
docker run -it -v /workspace:/usr/share/workspace sumumm/docker-demo:1.0.0 /bin/bash

# 方法 2:--mount 参数
docker run -it --mount type=bind,src=/workspace,dst=/usr/share/workspace sumumm/docker-demo:1.0.0 /bin/bash

3. 使用示例

3.1 挂载目录

shell
docker run -it --mount type=bind,src=/workspace,dst=/usr/share/workspace sumumm/docker-demo:1.0.0 /bin/bash

3.2 效果测试

原来 settings.json 文件内容如下:

bash
root@4ac5e5124ed5:/usr/share/workspace# cat settings.json
{
    "workbench.colorTheme": "One Dark Pro",
    "workbench.iconTheme": "material-icon-theme",
    "terminal.integrated.suggest.enabled": true
}

我们在宿主机把最后一个选项改为 false:

image-20251016074116855

然后再在容器内查看文件内容:

bash
root@4ac5e5124ed5:/usr/share/workspace# cat settings.json
{
    "workbench.colorTheme": "One Dark Pro",
    "workbench.iconTheme": "material-icon-theme",
    "terminal.integrated.suggest.enabled": false
}

我们在容器中创建一个文件并添加内容:

image-20251016074308766

会发现宿主机中也同步产生了文件。

四、总结

  • 数据持久性:

(1)默认存储方式下,容器内的数据会随着容器的删除而丢失,适合用于存储临时数据,容器间数据隔离且无需额外配置。

(2)使用 Volume/Bind Mount 存储方式时,数据由 Docker 统一管理,独立于容器生命周期,支持持久化存储和跨容器共享,便于备份和迁移。

  • 适用场景

(1)默认存储适用于临时数据场景,数据随容器删除而丢失,适合不需要长期保存的数据存储需求

(2)Volume 存储支持多容器共享和统一管理,数据持久化且独立于容器生命周期,便于备份和迁移

(3)BindMount 将主机目录直接挂载到容器,适合开发调试场景,可直接修改主机文件并实时生效

参考资料:

还在为 Docker 宿主机与容器文件共享发愁?看这一篇就够了!_docker 共享文件夹-CSDN 博客

(8 封私信) Docker 挂载本地目录和数据卷容器实现文件共享 - 知乎

dcoker 存储 —— One | 明心静性,爱自己

Docker 数据卷(Volume) - deshell - 博客园

莫道桑榆晚 为霞尚满天.