数据卷(容器数据管理)

数据卷(容器数据管理)


在不使用数据卷的情况下,修改 Nginx 的 HTML 页面时,需要进入 Nginx 容器内部操作,且容器内部没有编辑器,导致文件修改十分麻烦。

这就是 容器与数据(容器内文件)耦合 带来的问题:一旦需要修改容器内的文件,必须进入容器进行操作,不仅效率低下,还可能引发配置混乱。

要解决这个问题,必须将数据与容器解耦,这就需要使用 Docker 数据卷。通过将 Nginx 的静态资源(如 HTML 文件)挂载到宿主机的一个目录上,所有文件的修改都可以直接在宿主机上完成,无需进入容器内部操作。容器重启或更新也不会影响这些数据,这种方式既保持了容器的独立性,又简化了开发和运维过程。

image-20210731172440275

1. 数据卷是什么


数据卷(Volume) 是 Docker 提供的一种机制,用于在容器和宿主机之间共享和持久化数据。它可以将容器内的文件或目录映射到宿主机的某个目录中,从而实现数据的持久化,即使容器被删除,数据依然会保存。此外,数据卷也可以被多个容器共享。

当我们在使用数据卷时,实际上是在将容器中的某个目录挂载到宿主机上的某个目录,让容器和宿主机共享同一个数据存储位置。

假设有一个 Web 应用容器,它需要将用户上传的文件保存在容器中/usr/share/nginx/html 目录下。为了持久保存这些文件,可以使用 Docker 数据卷挂载,而不指定宿主机目录。数据卷会由 Docker 管理,即使容器被删除,数据也会保留。

1
docker run -v html:/usr/share/nginx/html ...
  • **-v html:/usr/share/nginx/html**:将名为 html 的 Docker 数据卷挂载到容器的
  • /usr/share/nginx/html 目录。如果数据卷 html 不存在,Docker 会自动创建它。

image-20210731173541846

执行 docker run -v html:/usr/share/nginx/html 条命令时,Docker 会将容器内的路径 /usr/share/nginx/html 挂载到 html 的数据卷上,这个数据卷会存储在宿主机的某个目录中,具体存储路径由 Docker 自动管理。

要查看这个数据卷在宿主机上的真实存储路径,使用命令:

1
docker volume inspect html

这个命令会输出数据卷的详细信息,包括它在宿主机上的实际存储路径。输出中会有一个类似于 Mountpoint 的字段,这就是该数据卷在宿主机上的实际存储位置。例如:

1
2
3
4
5
6
7
8
[
{
"Name": "html",
"Driver": "local",
"Mountpoint": "/var/lib/docker/volumes/html/_data",
...
}
]

在这个例子中,数据卷 html 的实际存储路径为宿主机的 /var/lib/docker/volumes/html/_data 目录。即使容器被删除,挂载在这个数据卷上的文件仍然保存在这个路径中。

2. 数据卷操作命令


数据卷操作的基本语法docker volume [COMMAND],根据COMMAND的不同执行不一样的指令。

  • create:创建一个新的数据卷。
  • inspect:显示一个或多个数据卷的详细信息。
  • ls:列出所有已创建的数据卷。
  • prune:删除所有未使用的数据卷,释放空间。
  • rm:删除一个或多个指定的数据卷。

2.1 创建数据卷

  • docker volume create 目录名称

例:创建一个html的数据卷。

1
docker volume create html
{70BD92FF-012C-4E13-AE72-CA247697940C}

可以在创建容器的时候直接由docker创建数据卷,挂载数据卷。

1
docker run --name mn -v html:/usr/share/nginx/html -p 80:80 -d nginx

2.2 查看数据卷

2.2.1 查看所有数据卷

  • docker volume ls

例:

{9A626326-03D1-4E92-A1AD-AD9907A21CB4}

2.2.2 查看数据卷详情

  • docker volume inspect 目录

例:查看html目录详情。

1
docker volume inspect html
{9C64F672-59EE-402D-BE6F-F5090193A6E1}

创建的html数据卷关联的宿主机目录为/var/lib/docker/volumes/html/_data目录。

2.3 删除数据卷

2.3.1 删除指定数据卷

  • docker volume rm 数据卷

例:删除html数据卷。

1
docker volume rm html
{E6DDB3E4-E318-4719-884D-6DCA6E08CAE4}

2.3.2 删除所有未使用的数据卷

  • docker volume prune

例:

{3FFCCE4C-97F3-499C-AD99-2C08DEF0F8F3}

3. 目录挂载


目录挂载(Bind Mount)是 Docker 中的一种机制,用于将宿主机上的具体目录手动的挂载到容器内的目录。这种方式允许容器访问和操作宿主机上的文件系统,实现文件和数据在宿主机和容器之间的共享。

用户手动指定宿主机的绝对路径和容器内的路径进行绑定。宿主机的目录必须是现有的,Docker 不会自动创建宿主机的目录。

3.1 目录挂载和数据卷挂载的相同点

  1. 持久化数据:两者都可以用于持久化容器中的数据。即使容器被删除或停止,数据依然保存在宿主机上,可以被新启动的容器再次使用。
  2. 共享数据:两者都能让多个容器共享相同的数据。当两个或多个容器使用同样的挂载点(数据卷或宿主机目录),它们可以同时访问和修改这些数据。
  3. 读写方式:在容器内,它们都表现为标准的文件目录,应用程序可以像操作本地文件系统一样读写数据。

3.2 目录挂载和数据卷挂载的区别

特性 目录挂载(Bind Mount) 数据卷挂载(Volume)
创建方式 需要手动指定宿主机上的目录路径。 Docker 自动管理,路径由 Docker 决定。
管理方式 宿主机目录完全由用户管理。 数据卷由 Docker 管理,包括其存储位置和生命周期。
使用命令 docker run -v /host/path:/container/path docker run -v volume_name:/container/path
宿主机依赖 强烈依赖宿主机的目录结构,如果宿主机上的目录不存在,Docker 会报错。 宿主机路径与具体的目录结构无关,Docker 会自动创建数据卷。
性能 在某些平台(如 Linux),性能没有显著差异。 数据卷通常在 Docker 上有较好的性能优化。
可移植性 由于绑定到宿主机的具体路径,跨平台或跨主机使用时可能出现问题。 数据卷是 Docker 自己管理的,具备更高的可移植性。
备份与恢复 手动管理备份和恢复,需要直接访问宿主机上的目录。 Docker 提供了专门的命令来备份和恢复数据卷。
访问权限 宿主机上的目录权限直接影响容器访问该目录的能力。 数据卷由 Docker 管理,权限相对独立,安全性更好。

3.3 示例

  • 目录挂载

    1
    docker run -v /data/uploads:/usr/share/nginx/html nginx
    • 容器的 /usr/share/nginx/html 目录与宿主机上的 /data/uploads 目录挂载在一起,数据实际存储在 /data/uploads,用户可以直接在宿主机上操作这些文件。
  • 数据卷挂载

    1
    docker run -v html:/usr/share/nginx/html nginx
    • 这里创建了一个名为 html 的数据卷,并将它挂载到容器的 /usr/share/nginx/html 目录,数据由 Docker 存储在宿主机上某个默认路径(如 /var/lib/docker/volumes),但不需要用户手动管理。

3.4 选用场景

  1. 目录挂载适合

    • 需要直接访问宿主机上的目录(如配置文件、日志文件等)。
    • 需要将特定的宿主机目录与容器同步,例如开发环境中修改代码后立即生效
  2. 数据卷挂载适合

    • 希望由 Docker 管理数据的生命周期,不需要关心宿主机的具体路径。
    • 希望在容器之间共享数据或跨主机(使用 Docker Swarm 或 Kubernetes)使用数据。
    • 更高的可移植性和性能优化需求。