Docker 学习笔记:存储篇

本笔记聚焦 Docker 存储的两种机制:镜像层与 Data Volume。详细讲解 bind mount、docker managed volume、volume container 和 data-packed volume container 的用法,以及 volume 的备份、恢复、迁移与销毁。


22. Docker 的两类存储资源

Docker 为容器提供两种存放数据的资源:

  1. 由 storage driver 管理的镜像层与容器层
  2. Data Volume(数据卷)

22.1 storage driver 与分层结构

  • 镜像由多个只读层堆叠,容器在最上面添加一个可写层。
  • Copy-on-Write 特性:
    • 新增数据直接写入容器层。
    • 修改数据时,先将镜像层数据复制到容器层,再修改。
    • 删除数据时,在容器层创建 whiteout 文件遮挡下层。
  • 不同 storage driver(如 overlay2、aufs、devicemapper 等)实现分层存储,推荐使用 Linux 发行版默认 driver。

bash

$ docker info | grep "Storage Driver"
Storage Driver: overlay2

适用场景:无状态应用,如 busybox 工具箱,数据不需要持久化。


23. Data Volume 之 bind mount

Data Volume 是宿主机文件系统中的目录或文件,直接挂载到容器内,具有以下特点:

  • 数据可永久保存,即使容器被删除。
  • 可被多个容器共享。

23.1 bind mount 操作

将宿主机目录 $HOME/htdocs 挂载到 httpd 容器的 /usr/local/apache2/htdocs

bash

$ mkdir ~/htdocs
$ echo '<html><body><h1>This is a file in host file system!</h1></body></html>' > ~/htdocs/index.html

$ docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
$ curl 127.0.0.1:80
<html><body><h1>This is a file in host file system!</h1></body></html>

更新内容(在宿主机修改文件):

bash

$ echo "updated index page!" > ~/htdocs/index.html
$ curl 127.0.0.1:80
updated index page!

容器删除后,bind mount 数据仍然保留

bash

$ docker stop <容器ID> && docker rm <容器ID>
$ cat ~/htdocs/index.html
updated index page!

23.2 只读 bind mount

bash

$ docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs:ro httpd
$ docker exec -it <容器ID> bash
root@xxx:/usr/local/apache2# echo "test" > htdocs/index.html
bash: htdocs/index.html: Read-only file system

23.3 绑定单个文件

bash

$ docker run -d -p 80:80 -v ~/htdocs/index.html:/usr/local/apache2/htdocs/new_index.html httpd
$ curl 127.0.0.1:80/new_index.html
updated index page!

注意:宿主机源文件必须存在,否则会被当作目录创建。

特点

  • 路径可任意指定。
  • 会隐藏容器内原有挂载点内容,替换为宿主机内容。
  • 移植性较弱(依赖宿主机特定路径)。

24. Data Volume 之 docker managed volume

使用 -v 只指定容器内路径,不指定宿主机路径,Docker 会自动在 /var/lib/docker/volumes/ 下创建 volume。

bash

$ docker run -d -p 80:80 -v /usr/local/apache2/htdocs httpd
$ docker inspect <容器ID>
"Mounts": [
    {
        "Type": "volume",
        "Name": "1cc915096121dea197bbbb93fc90e6491d530e0c9e2ace1de07e2a635e569d16",
        "Source": "/var/lib/docker/volumes/1cc915096121dea197bbbb93fc90e6491d530e0c9e2ace1de07e2a635e569d16/_data",
        "Destination": "/usr/local/apache2/htdocs",
        ...
    }
]

特点

  • 路径由 Docker 自动管理,移植性好。
  • 容器原有数据会被复制到 volume 中(若挂载点有数据)。
  • 不支持单个文件,只能是目录。
  • 读写权限不可控(均为读写)。

常用命令

bash

$ docker volume ls                     # 列出所有 volume
$ docker volume inspect <volume名>     # 查看 volume 详情
$ docker volume prune                  # 删除所有未使用的 volume

bind mount 与 docker managed volume 对比

特性 bind mount docker managed volume
volume 位置 任意指定 /var/lib/docker/volumes/...
对已有 mount point 影响 隐藏并替换 原有数据复制到 volume
是否支持单个文件 支持 不支持(仅目录)
权限控制 可设只读 无控制,均为读写
移植性 弱,依赖 host path 强,无需指定 host 目录

25. 如何共享数据

25.1 容器与宿主机共享数据

bind mount 直接共享;docker managed volume 可通过 docker cp 或直接操作 /var/lib/docker/volumes/ 目录传输数据。

bash

$ docker run -d -p 80:80 -v /usr/local/apache2/htdocs httpd
$ docker cp ~/htdocs/index.html <容器ID>:/usr/local/apache2/htdocs
$ curl 127.0.0.1:80
updated index page!

25.2 容器之间共享数据(bind mount)

创建三个 httpd 容器,都挂载同一宿主机目录:

bash

$ docker run --name web1 -d -p 80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
$ docker run --name web2 -d -p 80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
$ docker run --name web3 -d -p 80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
$ echo "shared by bind mount" > ~/htdocs/index.html
$ curl 127.0.0.1:<web1端口>
shared by bind mount

26. 用 volume container 共享数据

volume container 是专门为其他容器提供 volume 的容器,其本身不必运行。

26.1 创建 volume container

bash

$ docker create --name vc_data \
    -v ~/htdocs:/usr/local/apache2/htdocs \
    -v /other/useful/tools \
    busybox

此容器挂载了两个 volume:一个 bind mount,一个 docker managed volume。

26.2 其他容器使用 --volumes-from

bash

$ docker run --name web1 -d -p 80 --volumes-from vc_data httpd
$ docker run --name web2 -d -p 80 --volumes-from vc_data httpd
$ docker run --name web3 -d -p 80 --volumes-from vc_data httpd
$ docker inspect web1   # 查看 Mounts,与 vc_data 的 volume 相同

优点

  • 解耦容器与宿主机路径,所有 volume 定义集中在 volume container。
  • 挂载点一致,配置规范。

27. data-packed volume container

将数据直接打包进镜像,并通过 VOLUME 指令自动创建 docker managed volume,使数据完全自包含。

27.1 构建 data-packed 镜像

dockerfile

FROM busybox:latest
ADD htdocs /usr/local/apache2/htdocs
VOLUME /usr/local/apache2/htdocs

bash

$ echo "This content is from a data packed volume container!" > htdocs/index.html
$ docker build -t datapacked .

27.2 使用 data-packed volume container

bash

$ docker create --name vc_data datapacked
$ docker run -d -p 80:80 --volumes-from vc_data httpd
$ curl 127.0.0.1:80
This content is from a data packed volume container!

优点:移植性极强,不依赖宿主机任何数据。
适用场景:静态数据(配置、网页文件等)。


28. volume 生命周期管理

28.1 备份

volume 实质是宿主机目录,备份即备份对应目录文件。

28.2 恢复

将备份数据拷贝回原 volume 目录即可。

28.3 迁移

bash

# 停止原容器
$ docker stop <容器ID>
# 使用相同 volume 挂载启动新版本容器
$ docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:latest

28.4 销毁

  • bind mount:Docker 不会删除,需宿主机手动处理。

  • docker managed volume

    • 删除容器时加 -vdocker rm -v <容器ID>(前提是无其他容器使用该 volume)。

    • 孤儿 volume 的清理:

      bash

      $ docker volume ls
      $ docker volume rm <volume名>
      $ docker volume prune       # 批量删除未使用的 volume
      

29. 知识点速查表

29.1 两种存储资源对比

类型 管理方式 持久性 适用场景
镜像层与容器层 storage driver (overlay2 等) 容器删除即丢失 无状态应用
Data Volume bind mount / docker managed volume 持久 数据库、日志、配置等有状态数据

29.2 Data Volume 类型对比

特性 bind mount docker managed volume
创建方式 -v 宿主机路径:容器路径 -v 容器路径
位置 任意指定 /var/lib/docker/volumes/<id>/_data
移植性
权限控制 支持只读 不支持
单文件挂载 支持 不支持

29.3 数据共享方案对比

方案 优点 缺点
bind mount 多容器挂载 直接、灵活 依赖宿主机路径,移植性差
volume container 解耦路径,配置集中 需额外容器
data-packed volume container 完全自包含,可移植性最高 仅适合静态数据

29.4 常用 volume 管理命令

命令 功能
docker volume ls 列出所有 volume
docker volume create <name> 创建命名 volume
docker volume inspect <name> 查看 volume 详情
docker volume rm <name> 删除 volume
docker volume prune 删除所有未使用的 volume
docker run -v <宿主机路径>:<容器路径> bind mount
docker run -v <容器路径> docker managed volume
docker run --volumes-from <容器> 使用其他容器的 volume
docker rm -v <容器> 删除容器并删除其独占 volume

存储章节到此结束,接下来将进入容器监控与日志管理的学习。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐