单个文件卷作为目录安装在Docker中

时间:2015-12-07 13:07:13

标签: linux docker dockerfile

Docker documentation说可以将单个文件挂载到Docker容器中:

  

-v标志也可用于从主机安装单个文件 - 而不仅仅是目录。

     

$ docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash

     

这将使您进入新容器中的bash shell,您将获得主机的bash历史记录,当您退出容器时,主机将具有在容器中键入的命令的历史记录。

当我尝试这个时,文件将作为目录安装:

tom@u ~/project $ docker run --rm -it -v file.json:/file.json test
total 80K
drwxr-xr-x  9 root root 4.0K Dec  7 12:58 .
drwxr-xr-x 63 root root 4.0K Dec  7 12:58 ..
drwxr-xr-x  2 root root 4.0K Dec  4 16:10 file.json

我的Dockerfile如下所示:

FROM ubuntu:14.04
MAINTAINER Tom
CMD ["ls", "-lah", "/test"]

Docker版本为1.9.1,构建a34a1d5。

这是一个文档问题,对我有误解,还是还有其他事情发生?

6 个答案:

答案 0 :(得分:38)

也许上面的答案很明确......但我花了一些时间才弄明白。

导致与-v共享文件的基本原因是作为目录而不是文件显示,Docker无法在主机上找到该文件。所以Docker在容器中创建一个新目录,其名称是主机上非现有文件的名称,因为docker认为用户只想共享将来创建的卷/目录。

因此,在上面报告的问题中,如果在-v命令中使用了相对目录,并且docker不了解相关目录,则表示在主机上找不到该文件,因此docker创建了一个目录。上面的答案表明,当问题是由相对目录引起时,使用$(pwd)将是正确的解决方案。

但是对于那些阅读本页但没有使用相对目录并且遇到同样问题的人...然后尝试理解主机上缺少文件的原因。

这可能只是一个愚蠢的错字......

可能是您从客户端运行“docker run”命令,该客户端在另一台主机上生成docker容器,并且该共享文件不存在于该主机上。与-v共享的文件必须存在于docker agent将生成容器的主机上...不一定在执行“docker run -v ...”命令的客户端上(尽管它们在很多情况)。

对于Mac和Windows,还有其他可能的解释......也可能就是这样。

因此主机中丢失的文件是问题...解决您的设置中的问题...使用$(pwd)可能是解决方案,但并非总是如此。

答案 1 :(得分:32)

test是您使用“docker build -t test”而不是/test文件夹构建的图片名称。

尝试使用Dockerfile

CMD ["ls", "-lah", "/"]
or
CMD ["cat", "/file.json"]

docker run --rm -it -v $(pwd)/file.json:/file.json test

注意使用$(pwd)来安装具有完整绝对路径的文件(不支持相对路径)

答案 2 :(得分:19)

我花了一些时间与Windows上运行docker的问题并进行诊断。这也可能影响在Mac OSX上运行的人,所以我在这里为可能在这些环境中出现问题的人添加了一个答案,因为我的搜索带我到这个地方并添加了对docker中发生的事情的解释。

在Windows或Mac OSX中,您的docker实际上在boot2docker VM中运行,默认情况下,实际上只共享users目录。在Windows上,此用户目录以/ c / Users /共享,但是在Docker Machine附带的MinGW shell中,驱动器可以作为/ C或/ c访问,因此如果您忘记了docker命令,这可能会让您感到疯狂实际上是针对boot2docker虚拟机运行的,你的文件路径必须存在于boot2docker虚拟机上并以它们存在的方式指定,因为在docker中出现的情况是,而不是发出目录/文件所做的警告或错误不存在,docker默默地将指定的源创建为boot2docker VM中的目录,因此没有就绪输出来指示您正在执行任何错误操作。

因此,如上面的答案所示,如果您的文件作为目录挂载,请检查您是否提供了绝对路径。对于Windows和Mac OSX,请检查您正在装载的绝对路径是否存在于boot2docker VM中。

答案 3 :(得分:1)

对于那些使用VirtualBox机器的人来说,有一个简单的解决方案。 默认情况下,添加C:/ User文件夹。如果您的项目位于C:/ projects中,请添加此文件夹以使其在VB中可用(使用automount)。

答案 4 :(得分:1)

在docker内部运行docker时(例如,通过挂载<html> <body> <div id="app"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.0/vuex.min.js"></script> </body> </html>),您需要注意,如果在docker内部进行挂载,则使用的文件路径始终是主机上的文件路径。

因此,如果在主机上进行以下安装:

/var/run/docker.sock

您不应该在docker内部进行以下安装:

-v /tmp/foobar.txt:/my/path/foobar.txt

,但是使用主机文件路径,例如:

-v /my/path/foobar.txt:/my/other/path.txt

答案 5 :(得分:0)

即使您确定文件存在,Docker也可能找不到文件的情况

如edi9999所指出的那样,如果您告诉docker守护程序挂载文件,它将不会查看您当前容器的文件系统,而是会查看该守护程序运行所在的文件系统。

如果您的docker守护程序出于某种原因在其他地方运行,则可能会出现此问题。

❯ docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock docker
/ # echo "bar" > /foo
/ # docker run --rm -v /foo:/foo ubuntu bash -c 'cat foo'
cat: foo: Is a directory

Docker无法在其主机上找到/ foo文件,因此它(有帮助吗?)在该主机上创建了一个目录,因此至少您已经挂载了一些东西。

解决方法

您可以通过以下方法解决此问题:将主机目录装入外部容器,然后将该目录用于要显示在内部容器中的卷:

❯ docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock -v /dev/shm:/dev/shm docker
/ # echo "bar" > /dev/shm/foo
/ # docker run --rm -v /dev/shm/foo:/dev/shm/foo ubuntu bash -c 'cat /dev/shm/foo'
bar

这使路径/dev/shm/foo在任何上下文中都引用相同的文件,因此您可以从外部容器引用该文件,守护程序将在主机上找到它,这意味着它将显示为本身位于内部容器中,而不是作为目录。