如何管理Docker数据
更新:HHH   时间:2023-1-7


这篇文章主要介绍了如何管理Docker数据,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

管理Docker数据

在容器的可写层可以存储数据,但是有如下缺点:

  • 容器不再运行时,数据将不会持续存在,数据很难从容器中取出。

  • 容器可写层与容器运行的宿主紧耦合。无法在不同主机之间很好的进行数据迁移。

  • 在容器可写层数据写入数据,需要一个storage driver来管理文件系统。数据写入容器的读写层需要内核提供联合文件系统,相比使用data volumes直接写数据到宿主文件系统,这种抽象会带来开销。

Docker提供了三种不同的管理宿主上容器数据的方式:volumes, bind mountstmpfs volumes.

选择合适的mount类型

无论你选择哪种mount 类型,在容器中看到的数据都相同。即在容器文件系统中以目录或者独立文件的形式存在。

一种比较简单的方式区分 volumes, bind mounts 和 tmpfs mounts,是通过区分数据存放在Docker宿主的具体位置。

  • Volumes: 存放宿主文件系统下的 /var/lib/docker/volumes目录,非Docker进程不能修改这部分文件系统。Volumes是管理Docker持久化数据最好的方式。

  • Bind mounts: 存放在宿主的任意位置,可以是重要的系统文件或目录。非Docker进程和Docker容器可以随时修改这些数据。

  • tmpfs mounts:仅存在宿主系统的内存中,不会写入到宿主机的文件系统。

关于Mount类型的更多细节

  • Volumes:由Docker创建和管理。你可以通过docker volume create命令显式地创建volume,Docker也可以在创建容器或服务是自己创建volume。

当你创建了一个volume,它会被存放在宿主机的一个目录下。当你将这个volume挂载到某个容器时,这个目录就是挂载到容器的东西。这一点和bind mounts类似,除了volumes是由Docker创建的,和宿主机的核心(core functionality)隔离。

一个volume可以同时被挂载到几个容器中。即使没有正在运行的容器使用这个volume,volume依然存在,不会被自动清除。可以通过docker volume prune清除不再使用的volumes。

volumes也支持volume driver,可以将数据存放在另外的机器或者云上。

  • Bind mounts:Docker早期就支持这个特性。与volumes相比,Bind mounts支持的功能有限。使用bind mounts时,宿主机上的一个文件或目录被挂载到容器上。

警告:使用Bind mounts的一个副作用是,容器中运行的程序可以修改宿主机的文件系统,包括创建,修改,删除重要的系统文件或目录。这个功能可能会有安全问题。

  • tmpfs mounts:tmpfs mounts的数据不会落盘。在容器的生命周期内,它可以被用来存储一些不需要持久化的状态或敏感数据。例如,swarm服务通过tmpfs mounts来将secrets挂载到一个服务的容器中去。

适合Volumes的场景

volume 方式应该是持久化数据的首选方式, 其推荐用例:

  • 在不同的容器中共享数据。在多个容器之间共享数据,volume 在容器停止或删除的时候依然存在,如果需要删除需要显示(dockr rm -v…),多个容器可以加载相同的卷。 Volumes are only removed when you explicitly remove them.

  • 当主机不能保证有一个指定的目录或文件结构时。Volume有助于解耦容器runtime和Docker宿主配置。

  • 当需要把容器数据When you want to store your container’s data on a remote host or a cloud provider, rather than locally.

  • 当你需要备份、还原或迁移数据时。停止容器,备份卷的目录(如/var/lib/docker/volumes/<volume-name>。

适合bind mounts的场景

通过 bind mount 方式,你可以将你主机上的任何文件或目录(绝对路径)挂载到容器中。

  • 挂载的文件或目录可以被任何进程修改,因此有时候容器中修改了该文件或目录将会影响其他进程。

  • 如果挂载主机的文件或目录不存在将会自动创建。

  • 使用该方式不能通过 docker volume 管理,推荐使用 volume 方式。

  • 宿主机和容器共享配置文件。Docker提供的DNS解决方案就是如此,将宿主机的/etc/resolv.conf挂载到每个容器中。

  • 开发环境需要在宿主机和容器中共享代码。基于docker的开发就是如此,毕竟容器中一般是没有编辑器的。

  • Docker宿主上的文件和目录结构需要与容器中bind mount的目录保持一致。

如果将空文件或目录挂载到容器,容器中的该目录又有文件,那么,这些文件将会被复制到主机上的目录中。如果将非空的文件或目录挂载到容器,容器中的该目录也有文件,那么,容器中的文件将会被隐藏。

Volume VS. Bind mount

volume 在 docker 中被推荐为首选方式,它与 bind mount 相比,有以下优点:

  • 与 bind mount 相比,volume 更容易备份或迁移。

  • 可以使用 Docker CLI 命令或 Docker API 来管理。

  • volume 在 Linux 和 Windows 容器上都能工作。

  • volume 可以在多个容器之间更安全的共享。

  • volume 驱动程序允许你在远程主机或云上提供存储、加密或其他功能。

  • 新 volume 的内容可以由容器预填充。

配置 Propagation

Propagation 的在 bind mount 和 volume 中默认为 rprivate。它只能在 bind mount 配置,并且只能在 Linux 主机上配置。这是一个高级选项,许多用户不需要配置它。

Propagation 是指在给定的挂载卷或命名卷中创建的挂载是否可以传播到该挂载的副本。 考虑一个挂载点 /mnt,它被挂载在 /tmp。传播设置控制是否挂载 /tmp/a 也可用 /mnt/a。每个 Propagation 设置都有一个递归对应点。在递归的情况下,考虑 /tmp/a 被挂载为 /foo。传播设置控制是否 /mnt/a 或 /tmp/a 将存在。

Propagation 设置描述
shared原始mount的子mount会暴露给副本mount,并且副本mount的子mount也会传播到原始mount。
slave类似于共享的mount,但仅在一个方向上。如果原始mount显示一个子mount,副本mount可以看到它。但是,如果副本mount公开了子mount,则原始mount无法看到它。
private这个mount是私人的。其中的子mount不会暴露给副本mount,并且副mount的子mount不会暴露给原始mount。
rshared与共享相同,但是传播也扩展到嵌套在任何原始或副本mount点内的挂载点。
rslave与从属设备相同,但传播也延伸到嵌套在任何原始或副本mount点内的挂载点。
rprivate默认。与私有相同,这意味着在原始或副本mount点内的任何位置都不会有mount点向任一方向传播。

在可以在安装点上设置绑定传播之前,主机文件系统需要已经支持绑定传播。有关绑定传播的更多信息,请参阅 共享子树 的 Linux内核文档。

以下示例将 target/ 目录装载到容器中两次,第二个装入设置 ro 选项和 rslave 绑定传播选项。

在 --mount 和 -v 实例有同样的结果。

$ docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,target=/app \
  --mount type=bind,source="$(pwd)"/target,target=/app2,readonly,bind-propagation=rslave \
  nginx:latest


$ docker run -d \
  -it \
  --name devtest \
  -v "$(pwd)"/target:/app \
  -v "$(pwd)"/target:/app2:ro,rslave \
  nginx:latest

现在如果你创建 /app/foo/,/app2/foo/ 也将存在。

配置selinux标签

如果使用的 selinux 话,可以添加 z 或者 Z 选项来修改正在装入容器的主机文件或目录的 selinux 标签。这会影响主机本身的文件或目录,并可能导致Docker范围之外的后果。

  • 该 z 选项指示绑定安装内容在多个容器之间共享。

  • 该 Z 选项指示绑定安装内容是私有的和非共享的。

使用极端谨慎使用这些选项。绑定一个系统目录,例如 /home或者 /usr 用这个 Z 选项,将会使你的主机无法工作,你可能需要手工重新标记主机文件。

重要:在使用绑定安装服务时,selinux标签(:Z 和 :z)以及 :ro 被忽略。有关详细信息,请参阅 moby/moby#32579。

这个例子设置 z 选项来指定多个容器可以共享绑定挂载的内容:

使用 --mount 标志来修改selinux标签是不可能的。

$ docker run -d \
  -it \
  --name devtest \
  -v "$(pwd)"/target:/app:z \
  nginx:latest

配置macOS的安装一致性

Docker for Mac用于 osxfs 将从 macOS 共享的目录和文件传播到 Linux VM。这种传播使这些目录和文件可用于在 Docker for Mac 上运行的 Docker 容器。

默认情况下,这些共享是完全一致的,这意味着每次在 macOS 主机上发生写入或通过容器中的挂载时,都会将更改刷新到磁盘,以便共享中的所有参与者都具有完全一致的视图。在某些情况下,完全一致可能会严重影响性能。Docker 17.05 和更高版本引入了选项来调整一个一个,每个容器的一致性设置。以下选项可用:

  • consistent 或者 default:完全一致的默认设置,如上所述。

  • delegated:容器运行时的挂载视图是权威的。在容器中进行的更新可能在主机上可见之前可能会有延迟。

  • cached:macOS主机的挂载视图是权威的。在主机上进行的更新在容器中可见之前可能会有延迟。 这些选项在除 macOS 以外的所有主机操作系统上完全忽略。

在–mount和-v实例有同样的结果。

$ docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,destination=/app,consistency=cached \
  nginx:latest

$ docker run -d \
  -it \
  --name devtest \
  -v "$(pwd)"/target:/app:cached \
  nginx:latest

适合tmpfs mounts的场景

tmpfs mounts主要用在你既不想在容器内,又不想在宿主机文件系统保存数据的时候。这可能是出于安全原因,也可能是你的应用需要写非常多的非持久化数据,tmpfs mounts这时候可以保证容器性能。

相关用例

tmpfs,使用它的情况一般是,对安全比较重视以及不需要持久化数据。

使用方式

--tmpfs 和 --mount 的关系与前面两种方式的关系不用多说。那它们之间的差异是:

--tmpfs 不允许指定任何可配置选项。
--tmpfs 不能用于 swarm service,必须使用 --mount。

tmpfs 容器的限制

tmpfs 挂载不能在容器间共享。 tmpfs 只能在 Linux 容器上工作,不能在 windows 容器上工作。

容器中使用 tmpfs

$ docker run -d \
  -it \
  --name tmptest \
  --mount type=tmpfs,destination=/app \
  nginx:latest

$ docker run -d \
  -it \
  --name tmptest \
  --tmpfs /app \
  nginx:latest

tmpfs 通过运行 docker container inspect tmptest 并查找 Mounts 部分来验证安装是挂载:

"Tmpfs": {
    "/app": ""
},

删除容器:

$ docker container stop tmptest

$ Docker container rm tmptest

指定 tmpfs 选项

tmpfs 挂载允许两个配置选项,这两个都是不需要的。如果您需要指定这些选项,则必须使用该 --mount 标志,因为该 --tmpfs 标志不支持它们。

选项描述
tmpfs-sizetmpfs 的大小,以字节为单位。无限制默认。
tmpfs-modetmpfs 的八进制文件模式。例如,700 或者 0770。默认为 1777 或全局可写。

以下示例将设置 tmpfs-mode 为 1770,以便在容器内不可全局读取。

docker run -d \
  -it \
  --name tmptest \
  --mount type=tmpfs,destination=/app,tmpfs-mode=1770 \
  nginx:latest

感谢你能够认真阅读完这篇文章,希望小编分享的“如何管理Docker数据”这篇文章对大家有帮助,同时也希望大家多多支持天达云,关注天达云行业资讯频道,更多相关知识等着你来学习!

返回云计算教程...