作者:萧俊瑄俊明纬伦 | 来源:互联网 | 2022-12-03 15:01
首先,我想明确表示我已经在研究这个主题方面做了尽职调查.非常密切相关的是这个问题,这并没有真正解决我的困惑.
我知道,当VOLUME
在Dockerfile中指定时,这指示Docker在容器的持续时间内创建一个未命名的卷,该容器被映射到其内部的指定目录.例如:
# Dockerfile
VOLUME ["/foo"]
这将创建一个卷来包含存储在/foo
容器内的任何数据.音量(通过观看时docker volume ls
)会显示为随机混乱的数字.
每次执行docker run
此操作时,不会重复使用此卷.这是引起混淆的关键点.对我来说,卷的目标是在所有映像实例中包含状态持久性(所有容器都从它开始).所以基本上如果我这样做,没有明确的卷映射:
#!/usr/bin/env bash
# Run container for the first time
docker run -t foo
# Kill the container and re-run it again. Note that the previous
# volume would now contain data because services running in `foo`
# would have written data to that volume.
docker container stop foo
docker container rm foo
# Run container a second time
docker run -t foo
我希望在两个run
命令之间重用未命名的卷.然而,这种情况并非如此.因为我没有通过-v
选项显式映射卷,所以为每个选项创建了一个新卷run
.
这里有重要的第2部分:由于我需要明确指定-v
在run
命令之间共享持久状态,为什么我要VOLUME
在Dockerfile中指定?没有VOLUME
,我可以这样做(使用前面的例子):
#!/usr/bin/env bash
# Create a volume for state persistence
docker volume create foo_data
# Run container for the first time
docker run -t -v foo_data:/foo foo
# Kill the container and re-run it again. Note that the previous
# volume would now contain data because services running in `foo`
# would have written data to that volume.
docker container stop foo
docker container rm foo
# Run container a second time
docker run -t -v foo_data:/foo foo
现在,真的,第二个容器将安装数据,/foo
这是前一个实例的数据.我可以VOLUME
在我的Dockerfile中执行此操作.从命令行,我可以将容器内的任何目录转换为主机上的绑定目录或Docker中的卷.
所以我的问题是:VOLUME
当你必须通过主机上的命令显式地将命名卷映射到容器时,有什么意义呢?我要么缺少某些东西,要么就是混乱和混淆.
请注意,我在这里的所有断言都是基于我对docker行为的观察,以及我从文档中收集的内容.
1> King Chung H..:
像VOLUME
和EXPOSE
这样的指令有些不合时宜。我们今天所知道的命名卷是在大约三年前的Docker 1.9中引入的。
在Docker 1.9之前的版本中,运行一个其映像具有一个或多个VOLUME
指令(或使用该--volume
选项)的容器是创建用于数据共享或持久化的卷的唯一方法。实际上,过去的最佳实践是创建仅数据容器,其唯一目的是保存一个或多个卷,然后使用该--volumes-from
选项与应用程序容器共享这些卷。这是一些描述这种过时模式的文章。
Docker数据容器
为什么Docker数据容器(卷!)很好
另外,请查看moby / moby#17798(docker 1.9.0上已淘汰的仅数据容器?),其中讨论了从仅数据容器到命名卷的更改。
今天,我认为该VOLUME
说明是一种高级工具,仅在经过特殊考虑后,才应用于特殊情况。例如,官方的postgres图片声明VOLUME
为/var/lib/postgresql/data
。通过将数据库数据保留在分层文件系统之外,这可以提高现成的postgres容器的性能。Docker不必遍历容器映像的所有层以查找文件请求/var/lib/postgresql/data
。
但是,该VOLUME
指令确实要付出一定的代价。
用户可能不知道正在创建的未命名卷,并在删除容器后继续占用其Docker主机上的存储空间。
无法删除在Dockerfile中声明的卷。下游映像无法将数据添加到存在卷的路径。
后者会导致类似的问题。
如何在Docker镜像中“取消声明”卷?
Docker上的GitLab:如何在部署之间持久保存用户数据?
对于GitLab问题,有人希望使用预先配置的数据来扩展GitLab映像以进行测试,但是由于父映像中/ var / opt / gitlab的VOLUME,因此无法在下游映像中提交该数据。
tl; dr:VOLUME
是为Docker 1.9之前的世界设计的。最好只是把它留在外面。
我建议避免使用“ VOLUME”,但是“ EXPOSE”指令对于文档很有用。与“ VOLUME”不同,“ EXPOSE”指令没有任何有害的副作用。