在主机上的docker安装卷


135

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

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

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

VOLUME /path

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

Answers:


155

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,它将被卷的内容替换。


12
如果我在VOLUME中已指定的目录上使用-v,会发生什么情况?
杰夫·斯托里2014年

6
--volumes-from会将您安装VOLUME在您指定的任何内容之上-v。有趣的是,它看起来像以特权模式(docker run --privileged)运行容器,并且umounting /var/lib/mysql只会留下一个空目录,因此-v当它与冲突时,您的安装将被完全忽略VOLUME
克里斯·麦金奈尔

2
您说只要容器引用了卷,它们就会保留下来,而我在其他地方也看到过。 docs.docker.com/userguide/dockervolumes说:“数据卷旨在持久存储数据,与容器的生命周期无关。因此,Docker永远不会在删除容器时自动删除卷,也不会“垃圾收集”不再存在的卷被容器引用。” 这些陈述之一肯定是错误的。
mc0e 2015年

1
当容器不再引用该卷中的文件时,该卷中的文件将保留在磁盘上,但该卷本身不再可用(除非您确切地知道如何手动将卷挂接到容器上,但即使如此,我也不会这样做)不知道这是否可能)。当我说不再可用时,我的意思是您不能使用--volumes-from来使用它。当他们在上面说“垃圾收集”时,是指从磁盘中删除卷中的文件。
克里斯·麦金奈尔

1
它们可以使用-v来使用,但不能使用--volumes-from。Volumes-from使用容器名称来从中获取卷数据(我相信它需要所有卷点)。但是,对于-v本身,手册中提到您可以以-的形式为-v提供命名卷named-volume:/path/in/container。为未命名的卷提供了用于名称的哈希,可以提供这些哈希而不是用于访问孤立卷的主机路径。:)注意volume ls可能无法全部显示-也请尝试docker volume ls -f dangling=true
茉莉·黑格曼

44

让我添加我自己的答案,因为我相信其他人都缺少Docker的要点。

VOLUME在Dockerfile中使用的是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

如果Docker主机在VM中运行怎么办?例如,在Mac上为boot2docker。然后这些卷只能远程使用。同样,当按照您描述的那样在Dockerfile中使用卷时,映像的内容将被复制到该卷。但是,在装载到本地目录时,不会进行此复制。你知道为什么会这样吗?有没有办法在本地安装卷,但仍然“重新启动”映像中的文件?
LostSalad

4
使用docker-compose可以完全做到这一点,将卷安装在主机os的特定位置。无需符号链接...
Hugo Koopmans

@Tobia:例如搬运工-撰写看到的文档docs.docker.com/compose/compose-file/...
雨果库普曼斯

11

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

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

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

您将从容器1 /myvol目录中的所有数据进入容器2的相同位置。

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


8

基本上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-voption 之间的区别是可以-v在启动容器上动态使用option。这意味着您可以动态安装某些目录。另一个区别是您可以通过使用以下命令将主机目录挂载到容器上-v


8

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.