单个文件卷安装为 Docker 中的目录
Single file volume mounted as directory in Docker
Docker documentation 表示可以将单个文件装载到 Docker 容器中:
The -v flag can also be used to mount a single file - instead of just directories - from the host machine.
$ docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash
This will drop you into a bash shell in a new container, you will have your bash history from the host and when you exit the container, the host will have the history of the commands typed while in the container.
当我尝试这样做时,文件作为目录安装:
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
我的 Docker 文件如下所示:
FROM ubuntu:14.04
MAINTAINER Tom
CMD ["ls", "-lah", "/test"]
Docker版本为1.9.1,build a34a1d5.
这是文档问题,是我的误解,还是有其他问题?
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)
以使用完整的绝对路径挂载文件(不支持相对路径)
通过使用 $(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 中似乎发生的是 directory/file 不存在而不是给出警告或错误,docker在 boot2docker VM 中静默创建指定源作为目录,因此没有现成的输出表明您做错了什么。
因此,如上面的答案所示,如果您的文件作为目录挂载,请检查您是否提供了绝对路径。对于 Windows 和 Mac OSX 检查您正在安装的绝对路径是否存在于您的 boot2docker VM 中。
也许上面的答案很清楚...但我花了一些时间才弄清楚我的情况。
导致使用 -v 共享的文件显示为目录而不是文件的根本原因是 Docker 在主机上找不到该文件。因此 Docker 在容器中创建一个新目录,名称是主机上不存在的文件的名称,因为 docker 认为用户只想共享一个 volume/directory在未来创建。
所以在上面报告的问题中,如果你在 -v 命令中使用了相对目录,而 docker 不理解相对目录,这意味着在主机上找不到文件,所以 docker 创建了一个目录。当问题是由相对目录引起时,上面建议使用 $(pwd) 的答案将是正确的解决方案。
但对于那些阅读此页面但未使用相对目录且遇到相同问题的人...然后尝试了解主机上丢失文件的原因。
这可能只是一个愚蠢的错字...
可能是您 运行 来自客户端的 "docker run" 命令在另一台主机上生成了 docker 容器,而正在共享的文件在该主机上不存在不同的主机。与 -v 共享的文件必须存在于 docker 代理将生成容器的主机上...不一定存在于执行 "docker run -v ..." 命令的客户端上(尽管它们在许多情况)。
上面对 Mac 和 Windows 还有其他可能的解释...也可能是这样。
所以主机丢失的文件是问题所在...解决您设置中的问题...使用 $(pwd) 可能是解决方案,但并非总是如此。
对于使用 VirtualBox 机器的人来说,有一个简单的解决方案。
默认情况下,会添加 C:/User 文件夹。如果您的项目在 C:/projects 中,请添加此文件夹以使其在 VB 中可用(使用自动挂载)。
当运行 docker在docker内时(例如通过挂载/var/run/docker.sock
),你需要注意如果你在docker内挂载, 使用的文件路径始终是您主机上的文件路径。
因此,如果在您的主机上执行以下挂载:
-v /tmp/foobar.txt:/my/path/foobar.txt
你应该不在docker里面做下面的挂载:
-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
在任何上下文中都引用同一个文件,因此您可以从外部容器引用该文件,守护进程将在主机上找到它,这意味着它将显示在内部容器中作为其本身,而不是作为目录。
对于“Docker for Mac/Windows”用户,请确保您尝试从主机装载的卷是您“文件共享”首选项的一部分:
我在我的 MacBook 上遇到了与 Docker 在这里讨论的相同问题,none 的建议对我有用。事实证明,问题是我没有权限访问我试图挂载的文件(它由 root 拥有)。我将它复制到我的用户路径并将所有权更改为我自己,然后将文件挂载为文件而不是目录。我认为,如果您没有权限,Docker 会将其解释为该文件根本不存在,然后继续将其挂载为新目录
我会分享我的经验,我经常更改密码。我必须在 Docker Desktop For Windows 中“重置凭据”才能正确安装文件(当然,您应该确保文件位于共享路径中)
Docker documentation 表示可以将单个文件装载到 Docker 容器中:
The -v flag can also be used to mount a single file - instead of just directories - from the host machine.
$ docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash
This will drop you into a bash shell in a new container, you will have your bash history from the host and when you exit the container, the host will have the history of the commands typed while in the container.
当我尝试这样做时,文件作为目录安装:
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
我的 Docker 文件如下所示:
FROM ubuntu:14.04
MAINTAINER Tom
CMD ["ls", "-lah", "/test"]
Docker版本为1.9.1,build a34a1d5.
这是文档问题,是我的误解,还是有其他问题?
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)
以使用完整的绝对路径挂载文件(不支持相对路径)
通过使用 $(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 中似乎发生的是 directory/file 不存在而不是给出警告或错误,docker在 boot2docker VM 中静默创建指定源作为目录,因此没有现成的输出表明您做错了什么。
因此,如上面的答案所示,如果您的文件作为目录挂载,请检查您是否提供了绝对路径。对于 Windows 和 Mac OSX 检查您正在安装的绝对路径是否存在于您的 boot2docker VM 中。
也许上面的答案很清楚...但我花了一些时间才弄清楚我的情况。
导致使用 -v 共享的文件显示为目录而不是文件的根本原因是 Docker 在主机上找不到该文件。因此 Docker 在容器中创建一个新目录,名称是主机上不存在的文件的名称,因为 docker 认为用户只想共享一个 volume/directory在未来创建。
所以在上面报告的问题中,如果你在 -v 命令中使用了相对目录,而 docker 不理解相对目录,这意味着在主机上找不到文件,所以 docker 创建了一个目录。当问题是由相对目录引起时,上面建议使用 $(pwd) 的答案将是正确的解决方案。
但对于那些阅读此页面但未使用相对目录且遇到相同问题的人...然后尝试了解主机上丢失文件的原因。
这可能只是一个愚蠢的错字...
可能是您 运行 来自客户端的 "docker run" 命令在另一台主机上生成了 docker 容器,而正在共享的文件在该主机上不存在不同的主机。与 -v 共享的文件必须存在于 docker 代理将生成容器的主机上...不一定存在于执行 "docker run -v ..." 命令的客户端上(尽管它们在许多情况)。
上面对 Mac 和 Windows 还有其他可能的解释...也可能是这样。
所以主机丢失的文件是问题所在...解决您设置中的问题...使用 $(pwd) 可能是解决方案,但并非总是如此。
对于使用 VirtualBox 机器的人来说,有一个简单的解决方案。 默认情况下,会添加 C:/User 文件夹。如果您的项目在 C:/projects 中,请添加此文件夹以使其在 VB 中可用(使用自动挂载)。
当运行 docker在docker内时(例如通过挂载/var/run/docker.sock
),你需要注意如果你在docker内挂载, 使用的文件路径始终是您主机上的文件路径。
因此,如果在您的主机上执行以下挂载:
-v /tmp/foobar.txt:/my/path/foobar.txt
你应该不在docker里面做下面的挂载:
-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
在任何上下文中都引用同一个文件,因此您可以从外部容器引用该文件,守护进程将在主机上找到它,这意味着它将显示在内部容器中作为其本身,而不是作为目录。
对于“Docker for Mac/Windows”用户,请确保您尝试从主机装载的卷是您“文件共享”首选项的一部分:
我在我的 MacBook 上遇到了与 Docker 在这里讨论的相同问题,none 的建议对我有用。事实证明,问题是我没有权限访问我试图挂载的文件(它由 root 拥有)。我将它复制到我的用户路径并将所有权更改为我自己,然后将文件挂载为文件而不是目录。我认为,如果您没有权限,Docker 会将其解释为该文件根本不存在,然后继续将其挂载为新目录
我会分享我的经验,我经常更改密码。我必须在 Docker Desktop For Windows 中“重置凭据”才能正确安装文件(当然,您应该确保文件位于共享路径中)