148

我已经成功地能够使用卷在 docker 容器之间共享文件夹

docker run -v /host/path:/container/path ...

但我的问题是这与使用VOLUMEDockerfile 中的命令有什么区别

VOLUME /path

我正在使用具有VOLUME命令的图像,我想知道如何与我的主机共享它。我已经使用-v上面的命令完成了它,但我不知道我是否需要-vVOLUME.

4

6 回答 6

164

VOLUME命令将在容器内挂载一个目录,并将在该目录内创建或编辑的任何文件存储在容器文件结构之外的主机磁盘上,绕过联合文件系统。

这个想法是你的卷可以在你的 docker 容器之间共享,只要有一个容器(运行或停止)引用它们,它们就会一直存在。

您可以在运行容器时使用该--volumes-from命令让其他容器挂载现有卷(有效地在容器之间共享它们)。

VOLUME和之间的根本区别在于-v-v将操作系统中的现有文件挂载到 docker 容器中,VOLUME并将在主机上创建一个新的空卷并将其挂载到容器中。

例子:

  1. 你有一个 Dockerfile 定义了一个VOLUME /var/lib/mysql.
  2. 您构建 docker 映像并对其进行标记some-volume
  3. 你运行容器

接着,

  1. 您有另一个要使用此卷的 docker 映像
  2. 您使用以下命令运行 docker 容器: docker run --volumes-from some-volume docker-image-name:tag
  3. 现在您有一个正在运行的 docker 容器,该容器将从中some-volume安装卷/var/lib/mysql

注意:使用--volumes-from会将卷安装在卷所在位置的任何位置上。即,如果您在 中有东西/var/lib/mysql,它将被卷的内容替换。

于 2014-08-14T16:10:33.203 回答
52

让我添加我自己的答案,因为我相信其他人都错过了 Docker 的重点。

在 Dockerfile 中使用VOLUME是 Right Way™,因为您让 Docker 知道某个目录包含永久数据。Docker 将为该数据创建一个卷并且永远不会删除它,即使您删除了所有使用它的容器。

它还绕过了联合文件系统,因此该卷实际上是一个实际目录,它在共享它的所有容器中的正确位置安装(读写或只读)。

现在,为了从主机访问该数据,您只需要检查您的容器:

# docker inspect myapp
[{
    .
    .
    .
    "Volumes": {
        "/var/www": "/var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6...",
        "/var/cache/nginx": "/var/lib/docker/vfs/dir/62499e6b31cb3f7f59bf00d8a16b48d2...",
        "/var/log/nginx": "/var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87..."
    },
    "VolumesRW": {
        "/var/www": false,
        "/var/cache/nginx": true,
        "/var/log/nginx": true
    }
}]

我通常做的是在 /srv 等标准位置创建符号链接,以便我可以轻松访问卷并管理它们包含的数据(仅适用于您关心的卷):

ln -s /var/lib/docker/vfs/dir/b3ef4bc28fb39034dd7a3aab00e086e6... /srv/myapp-www
ln -s /var/lib/docker/vfs/dir/71896ce364ef919592f4e99c6e22ce87... /srv/myapp-log
于 2015-04-01T11:28:44.883 回答
13

VOLUME 用于Dockerfile暴露要被其他容器使用的卷。示例,创建Dockerfile为:

来自 ubuntu:14.04

RUN mkdir /myvol  
RUN echo "hello world" > /myvol/greeting  
VOLUME /myvol

构建图像:

$ docker build -t testing_volume .

运行容器,比如 container1:

$ docker run -it <image-id of above image> bash

现在运行另一个带有volumes-from选项的容器(say-container2)

$ docker run -it --volumes-from <id-of-above-container> ubuntu:14.04 bash

您将从 container1/myvol目录获取所有数据到同一位置的 container2。

-v选项在容器运行时给出,用于在主机上挂载容器的目录。它使用简单,只需提供-v带有参数的选项 as <host-path>:<container-path>。整个命令可能是$ docker run -v <host-path>:<container-path> <image-id>

于 2016-09-26T07:36:18.807 回答
9

基本上VOLUME-v选项几乎相等。这些意味着“在容器上挂载特定目录”。例如,VOLUME /data-v /data是完全一样的意思。如果您运行具有VOLUME /data或具有-v /data选项的图像,则/data目录将安装在您的容器中。此目录不属于您的容器。

想象一下,您在容器上添加了一些文件/data,然后将容器提交到新图像中。数据目录上没有任何文件,因为挂载/data的目录属于原始容器。

$ docker run -it -v /data --name volume ubuntu:14.04 bash
root@2b5e0f2d37cd:/# cd /data
root@2b5e0f2d37cd:/data# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/data# cd /tmp
root@2b5e0f2d37cd:/tmp# touch 1 2 3 4 5 6 7 8 9
root@2b5e0f2d37cd:/tmp# exit
exit

$ docker commit volume nacyot/volume  
835cfe3d8d159622507ba3256bb1c0b0d6e7c1419ae32751ad0f925c40378945
nacyot $ docker run -it nacyot/volume
root@dbe335c7e64d:/# cd /data
root@dbe335c7e64d:/data# ls
root@dbe335c7e64d:/data# cd /tmp
root@dbe335c7e64d:/tmp# ls
1  2  3  4  5  6  7  8  9
root@dbe335c7e64d:/tmp# 
root@dbe335c7e64d:/tmp# 

这个挂载的目录 like/data用于存储不属于您的应用程序的数据。并且可以通过使用预定义不属于容器的数据目录VOLUME

Volume和option的区别在于-v您可以-v在启动容器时动态使用 option。这意味着您可以动态挂载一些目录。另一个区别是您可以使用以下方法将主机目录安装在容器上-v

于 2014-08-14T16:16:46.450 回答
9

这来自 Docker 文档本身,可能会有所帮助,简单明了:

“主机目录本质上是依赖于主机的。因此,您不能从 Dockerfile 挂载主机目录,VOLUME 指令不支持传递主机目录,因为构建的图像应该是可移植的。主机目录不会在所有潜在主机上都可用。”。

于 2017-04-11T05:45:17.607 回答
1

如果您来这里是因为您正在寻找一种简单的方式来浏览任何VOLUME

  1. 找出卷的名称docker volume list
  2. 关闭此卷所附加到的所有正在运行的容器
  3. docker run -it --rm --mount source=[NAME OF VOLUME],target=/volume busybox
  4. 将打开一个外壳。cd /volume输入音量。
于 2020-10-22T11:43:18.310 回答