Dockerfile 中的 VOLUME 指令的目的是什么?

Sha*_*ane 7 docker

在文档中,它说 VOLUME 指令创建了一个口点,但我创建了一个图像使用

FROM alpine
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
Run Code Online (Sandbox Code Playgroud)

并且我能够在使用的容器文件系统上挂载 /myvol 或任何其他路径,docker run -v vol:/myvol myimage并且能够在主机上的 /var/lib/docker/vol/_data 中查看那里的数据。

添加VOLUME myvol到 Dockerfile 会有什么不同?

Cve*_*tk0 8

我一直在努力理解这一点,不得不做一些实际测试,因为文档对我来说有点模糊。

使用 Dockerfile 中的 VOLUME 指令,您可以显式声明从该映像创建的容器公开的卷,即使在容器创建时创建容器时未显式挂载该卷 - 例如docker run -v <volume>:/data <image name>.

相反,我可以在 Dockerfile 中有一个指令

FROM alpine

RUN mkdir /data && echo "Some data" > /data/mydata
VOLUME /data
Run Code Online (Sandbox Code Playgroud)

从使用上述 Dockerfile 构建的镜像启动容器:

docker run -ti --rm --name volume-test voltest
Run Code Online (Sandbox Code Playgroud)

检查正在运行的容器

docker container inspect volume-test

...
        "Mounts": [
            {
                "Type": "volume",
                "Name": "c4d070456dfa65540bd5c75b958930837bbf4277f4a4169b791679127f29a73a",
                "Source": "/var/snap/docker/common/var-lib-docker/volumes/c4d070456dfa65540bd5c75b958930837bbf4277f4a4169b791679127f29a73a/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ]
...
Run Code Online (Sandbox Code Playgroud)

如您所见,有一个卷挂载到容器的 /data 目录。这个匿名卷是在容器创建期间自动创建的,因为 Dockerfile 中的 VOLUME 指令,并且由于容器是用--rm选项启动的,它将在容器停止时自动删除(假设当时没有其他东西会使用它)。您可以docker volume ls在停止容器后使用来确认这一点。

这允许使用来自其他容器的此类临时卷,例如通过运行安装它们:

docker run --rm -ti --name alpine-vol --volumes-from volume-test alpine sh
Run Code Online (Sandbox Code Playgroud)

检查/data新启动的容器中的目录,它将包含原始容器写入卷上的数据。

当需要在容器之间共享数据但不需要在删除原始容器后保留(例如,作为 sidecar 模式的一部分)时,我肯定会使用它。如果需要数据持久性,您仍然可以将卷显式安装到同一目录中。


Mic*_*ton 2

VOLUME 的明显用途是用容器提供的数据填充新的持久卷。无论您要部署哪种类型的应用程序,几乎总是需要一些初始数据。该文档明确指出,此复制仅在新创建卷时发生。