繁体   English   中英

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

[英]Single file volume mounted as directory in Docker

Docker 文档说可以将单个文件挂载到 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。

这是文档问题,是我的误解,还是还有其他问题?

也许在上面的答案中很清楚......但我花了一些时间才弄清楚我的情况。

导致使用 -v 共享的文件显示为目录而不是文件的根本原因是 Docker 在主机上找不到该文件。 因此 Docker 在容器中创建一个新目录,名称是主机上不存在的文件的名称,因为 docker 认为用户只是想共享一个将来会创建的卷/目录。

所以在上面报告的问题中,如果你在 -v 命令中使用了相对目录,而 docker 不理解相对目录,那意味着在主机上找不到该文件,因此 docker 创建了一个目录。 当问题是由于相对目录时,上面建议使用 $(pwd) 的答案将是正确的解决方案。

但是对于那些阅读此页面的人来说,他们没有使用相对目录并且遇到同样的问题......然后尝试了解为什么主机上缺少文件。

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

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

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

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

test是您使用“ docker build -t testdocker 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)以安装具有完整绝对路径的文件(不支持相对路径)

通过使用$(pwd) ,您将获得一个确实存在的绝对路径,并尊重大小写,而不是可能不存在的文件名或路径。
不存在的主机路径将作为文件夹安装在容器中。

我花了一些时间来解决和诊断在 Windows 上运行 docker 的这个问题。 这也可能影响在 Mac OSX 上运行的人,因此我在此处为可能在这些环境中遇到问题的人添加了一个答案,因为我的搜索将我带到了这个地方,并添加了对 docker 中似乎发生的事情的解释。

在 Windows 或 Mac OSX 中,您的 docker 实际上是在 boot2docker VM 中运行的,并且默认情况下实际上只有用户目录是共享的。 在 Windows 上,这个用户目录被共享为 /c/Users/,但是在 Docker Machine 附带的 MinGW shell 中,驱动器可以作为 /C 或 /c 访问,所以如果你忘记了 docker 命令,这会让你抓狂实际上针对 boot2docker VM 运行,并且您的文件路径必须存在于 boot2docker VM 上,并以它们在那里存在的方式指定,因为 docker 中似乎发生的是,而不是给出目录/文件所做的警告或错误不存在,docker 会在 boot2docker VM 中静默创建指定的源作为目录,因此没有准备好的输出表明您正在做任何不正确的事情。

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

在 docker 中运行 docker 时(例如通过挂载/var/run/docker.sock ),您需要注意,如果您在 docker 中挂载,则使用的文件路径始终是您主机上的文件路径。

因此,如果在您的主机上执行以下挂载:

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

应该做以下安装内泊坞窗:

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

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

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

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在任一上下文中都引用同一个文件,因此您可以从外部容器引用该文件,守护进程将在主机上找到它,这意味着它将在内部容器,而不是目录。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM