码头主机安装卷

我已经成功地使用

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

但我的问题是,这与在 Dockerfile 使用 VOLUME命令有什么区别

VOLUME /path

我正在使用一个具有 VOLUME命令的映像,我想知道如何与我的主机共享它。我已经使用上面的 -v命令做到了这一点,但是我不知道我是否需要同时使用 -vVOLUME

200623 次浏览

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

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

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

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

例如:

  1. 您有一个定义 VOLUME /var/lib/mysql的 Dockerfile。
  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,它将被替换为卷的内容。

基本上 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#

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

Volume-v选项之间的区别在于,您可以在启动容器时动态使用 -v选项。这意味着您可以动态地挂载某个目录。另一个区别是,您可以使用 -v将主机目录挂载到容器上

让我补充一下我自己的答案,因为我相信其他人没有抓住 Docker 的要点。

在 Dockerfile 使用 VOLUME是正确的方式,因为你让 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

VOLUME 在 Dockerfile中用于公开其他容器所使用的卷。例如,按照以下方式创建 Dockerfile:

FROM ubuntu: 14.04来自 Ubuntu: 14.04

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

树立形象:

$ docker build -t testing_volume .

运行这个容器,比如说容器1:

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

现在运行另一个容器,选项为 voluloffrom (比如说-Container)

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

您将在同一位置将所有数据从 Container er1/myvol目录放入 Container er2。

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

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

”主机目录本质上是依赖于主机的。由于这个原因,你不能从 Dockerfile 挂载主机目录,VOLUME 指令不支持传递 host-dir,因为构建的映像应该是可移植的。并不是所有潜在的主机都有主机目录。”.

如果你来这里是为了寻找浏览任何 VOLUME的简单方法:

  1. 使用 docker volume list查找卷的名称
  2. 关闭该卷所连接的所有正在运行的容器
  3. 运行 docker run -it --rm --mount source=[NAME OF VOLUME],target=/volume busybox
  4. 将打开一个 shell。 cd /volume输入卷。