简而言之:不,您的VOLUME
指示不正确。
Dockerfile VOLUME
根据容器端路径指定一个或多个卷。但是它不允许图像作者指定主机路径。在主机端,在Docker根目录中使用非常长的类ID名称创建卷。在我的机器上是/var/lib/docker/volumes
。
注意:因为自动生成的名称非常长,并且从人类的角度来看是没有意义的,所以这些卷通常被称为“未命名”或“匿名”。
您的示例使用“。” 无论我将点设为第一个还是第二个参数,该字符甚至都不会在我的机器上运行。我收到此错误消息:
docker:来自守护程序的错误响应:oci运行时错误:container_linux.go:265:启动容器进程导致“ process_linux.go:368:容器初始化引起了\“ open / dev / ptmx:没有此类文件或目录\”。
我知道,到目前为止,对于试图理解的人来说,所说的内容可能不是很有价值VOLUME
,-v
并且它当然不能为您要实现的目标提供解决方案。因此,希望以下示例可以为这些问题提供更多的启示。
教程:指定卷
鉴于此Dockerfile:
FROM openjdk:8u131-jdk-alpine
VOLUME vol1 vol2
(对于本教程的结果,如果我们指定vol1 vol2
或/vol1 /vol2
-不要问我为什么,这没有什么区别)
建立它:
docker build -t my-openjdk
跑:
docker run --rm -it my-openjdk
在容器内,ls
在命令行中运行,您会注意到存在两个目录;/vol1
和/vol2
。
运行容器还会在主机端创建两个目录或“卷”。
在运行容器的同时,docker volume ls
在主机上执行操作,您将看到类似这样的内容(为简便起见,我用三个点代替了名称的中间部分):
DRIVER VOLUME NAME
local c984...e4fc
local f670...49f0
返回容器中,执行touch /vol1/weird-ass-file
(在所述位置创建一个空白文件)。
现在,该文件在主机上的未命名卷之一中可用。我进行了两次尝试,因为我首先尝试了第一个列出的卷,但是最终我在主机上使用此命令在第二个列出的卷中找到了我的文件:
sudo ls /var/lib/docker/volumes/f670...49f0/_data
同样,您可以尝试在主机上删除此文件,并且该文件也会在容器中删除。
注意:该_data
文件夹也称为“挂载点”。
从容器退出并列出主机上的卷。他们走了。我们--rm
在运行容器时使用了该标志,并且此选项不仅可以清除出口上的容器,还可以擦除卷。
运行一个新容器,但使用-v
以下命令指定卷:
docker run --rm -it -v /vol3 my-openjdk
这将添加第三个卷,整个系统最终将具有三个未命名的卷。如果仅指定,该命令将崩溃-v vol3
。参数必须是容器内的绝对路径。在主机端,新的第三个卷是匿名的,并与中的其他两个卷一起驻留。/var/lib/docker/volumes/
前面已经说过,Dockerfile
当尝试在运行时将文件从主机导入容器时,不能映射到主机路径,这给我们带来了问题。使用不同的-v
语法可以解决此问题。
想象一下,我在项目目录./src
中有一个子文件夹,希望将其同步到/src
容器中。此命令可以解决问题:
docker run -it -v $(pwd)/src:/src my-openjdk
:
角色的两面都希望有一条绝对的道路。左侧是主机上的绝对路径,右侧是容器内部的绝对路径。pwd
是“打印当前/工作目录”的命令。将该命令放入$()
括号中,将其运行在子外壳中,并返回到项目目录的绝对路径。
放在一起,假设我们./src/Hello.java
在主机上的项目文件夹中具有以下内容:
public class Hello {
public static void main(String... ignored) {
System.out.println("Hello, World!");
}
}
我们构建以下Dockerfile:
FROM openjdk:8u131-jdk-alpine
WORKDIR /src
ENTRYPOINT javac Hello.java && java Hello
我们运行以下命令:
docker run -v $(pwd)/src:/src my-openjdk
打印“你好,世界!”。
最好的部分是,我们可以完全自由地用新消息修改.java文件,以便在第二次运行时将其输出给另一个输出-无需重建image =)
结束语
我刚接触Docker,前面提到的“教程”反映了我从为期3天的命令行黑客马拉松中收集的信息。令我感到羞耻的是,我还无法提供链接来清除清晰的类似英语的文档来支持我的陈述,但是老实说,这是由于缺少文档而不是个人的努力。我确实知道示例使用我当前的设置“ Windows 10-> Vagrant 2.0.0-> Docker 17.09.0-ce”进行宣传。
本教程没有解决“我们如何在Dockerfile中指定容器的路径,而让run命令仅指定主机路径”的问题。可能有一种方法,我只是没有找到它。
最后,我有一种直觉,认为VOLUME
在Dockerfile 中指定不仅是不常见的,而且它是从不使用的最佳实践VOLUME
。有两个原因。我们已经确定的第一个原因:我们无法指定主机路径-这是一件好事,因为Dockerfiles应该与主机的具体情况无关。但是第二个原因是,人们可能会--rm
在运行容器时忘记使用该选项。一个人可能记得删除容器,但忘记删除卷。另外,即使拥有最好的人类记忆力,找出所有匿名卷中哪些可以安全删除也是一项艰巨的任务。