Dockerfile命令中的RUN在共享卷内找不到文件。

15 浏览
0 Comments

Dockerfile命令中的RUN在共享卷内找不到文件。

自2014年提出这个问题以来,发生了许多情况,许多事情发生了变化。今天我再次回顾这个话题,并第12次编辑这个问题以反映最新的变化。这个问题可能看起来很长,但它是按照倒序排列的,所以最新的变化在顶部,随时可以停止阅读。

我想解决的问题是 - 在构建过程中如何将主机卷挂载到Docker容器中的Dockerfile中,即在docker build期间具有docker run -v /export:/export的功能。

我之所以提出这个问题,一个原因是在使用Docker构建东西时,我不希望那些(apt-get install)缓存锁定在一个单独的docker中,而是共享/重用它们。

这是我提出这个问题的主要原因。还有一个原因是我今天面临的另一个原因是尝试使用主机上的一个巨大的私有仓库,否则我必须使用我的私有ssh密钥从docker内的私有仓库进行git clone,我不知道如何做,也没有研究过。

最新更新:

@BMitch答案中的Buildkit

使用RUN --mount语法,您还可以从构建上下文中绑定挂载只读目录...

它现在已经内置在docker中(我原以为它是第三方工具),只要您的版本18.09以上。我的版本是20.10.7 -

https://docs.docker.com/develop/develop-images/build_enhancements/

启用BuildKit构建

从全新安装的docker开始,最简单的方法是在调用docker build命令时设置DOCKER_BUILDKIT=1环境变量,例如:

$ DOCKER_BUILDKIT=1 docker build .

否则,您将获得以下提示:

the --mount option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled

所以对于我上面解释的第二个用例来说,这将是完美的解决方案。

更新至2019年5月7日:

在docker v18.09之前,正确的答案应该是以以下方式开始的答案:

有一种方法可以在构建过程中挂载卷,但不涉及Dockerfile。

然而,那个回答陈述不清楚、组织混乱且没有提供支持。当我重新安装我的docker容器时,我碰巧看到了下面的文章:

将apt-cacher-ng服务docker化

https://docs.docker.com/engine/examples/apt-cacher-ng/

这是docker对这个问题的解决方案,不是直接的,而是间接的。这是docker建议我们使用的正统方式。我承认这比我在这里尝试询问的方法更好。

另一种方法是接受的答案,即v18.09中的Buildkit。

选择适合您的方法。


过去:曾经有一个解决方案 - rocker,它不是来自Docker,但现在rocker已经停止,所以我又把答案改回“不可能”。


旧的更新:所以答案是“不可能”。我可以接受它作为一个答案,因为我知道这个问题在https://github.com/docker/docker/issues/3156上得到了广泛讨论。我可以理解可移植性对于Docker开发者来说是一个重要问题;但作为一个Docker用户,我必须说我对这个缺失的功能感到非常失望。让我用上述讨论中的一句话来结束我的论点:“我想使用Gentoo作为基本镜像,但绝对不希望在构建镜像后的任何层中出现超过1GB的Portage树数据。如果不是庞大的Portage树必须在安装过程中出现在镜像中,那么你可以有一些很好的紧凑容器。”是的,我可以使用wget或curl来下载我需要的任何东西,但仅仅是因为一个可移植性的考虑现在迫使我每次构建一个Gentoo基本镜像时下载超过1GB的Portage树,这既不高效也不用户友好。而且,软件包存储库将始终位于/usr/portage下,在Gentoo下始终是可移植的。再次强调,我尊重这个决定,但请同时允许我表达我的失望。谢谢。


详细的原始问题:

来源于

通过卷共享目录

http://docker.readthedocs.org/en/v0.7.3/use/working_with_volumes/

它说数据卷功能“自Docker远程API的第1版以来就可用”。我的docker版本是1.2.0,但我发现上述文章中给出的示例不起作用:

# 通过以下命令构建:        docker build -t data .
# 通过以下命令运行:          docker run -name DATA data
FROM          busybox
VOLUME        ["/var/volume1", "/var/volume2"]
CMD           ["/usr/bin/true"]

在Dockerfile中,使用VOLUME命令挂载主机挂载的卷的正确方式是什么?

$ apt-cache policy lxc-docker
lxc-docker:
  Installed: 1.2.0
  Candidate: 1.2.0
  Version table:
 *** 1.2.0 0
        500 https://get.docker.io/ubuntu/ docker/main amd64 Packages
        100 /var/lib/dpkg/status
$ cat Dockerfile 
FROM          debian:sid
VOLUME        ["/export"]
RUN ls -l /export
CMD ls -l /export
$ docker build -t data .
Sending build context to Docker daemon  2.56 kB
Sending build context to Docker daemon 
Step 0 : FROM          debian:sid
 ---> 77e97a48ce6a
Step 1 : VOLUME        ["/export"]
 ---> Using cache
 ---> 59b69b65a074
Step 2 : RUN ls -l /export
 ---> Running in df43c78d74be
total 0
 ---> 9d29a6eb263f
Removing intermediate container df43c78d74be
Step 3 : CMD ls -l /export
 ---> Running in 8e4916d3e390
 ---> d6e7e1c52551
Removing intermediate container 8e4916d3e390
Successfully built d6e7e1c52551
$ docker run data
total 0
$ ls -l /export | wc 
     20     162    1131
$ docker -v
Docker version 1.2.0, build fa7b24f

0
0 Comments

Dockerfile命令在共享卷中运行找不到文件的原因是Dockerfile本身的限制,无法在构建阶段挂载可重复使用的卷。这个问题可以通过使用Rocker来解决。Rocker是一个基于Docker的工具,通过引入新的命令来解决一些Dockerfile难以解决的问题。

Rocker的主要解决方案如下:

1. 在构建阶段挂载可重复使用的卷,以便依赖管理工具可以在构建之间使用缓存。

2. 在构建过程中共享ssh密钥,以便从私有仓库中拉取代码,同时又不将密钥保留在生成的镜像中。

3. 在不同的镜像中构建和运行应用程序,并且可以轻松地在镜像之间传递构件,最好将这个逻辑放在一个Dockerfile中。

4. 从Dockerfile中直接标记/推送镜像。

5. 通过shell构建命令传递变量,以便可以在Dockerfile中进行替换。

然而,需要注意的是,Rocker已经停止维护,因为在2018年,容器生态系统已经更加成熟,一些关键和突出特性已经可以通过docker build或其他成熟的工具进行支持。因此,可以使用这些工具来解决这些问题。

对于使用Rocker解决问题1的情况,可能出现挂载命令无法工作的问题。可能的原因是Dockerfile中的挂载路径不正确,可以尝试使用真实的主机路径,而不是使用Bourne shell的元字符"~"。

另外,Rocker的构建命令不支持docker run的命令行选项,如"--privileged",这也是一个需要注意的问题。

,Dockerfile命令在共享卷中运行找不到文件的问题可以通过使用Rocker来解决。但需要注意的是,Rocker已经停止维护,可以使用其他成熟的工具来解决类似的问题。

0
0 Comments

Docker是一个开源的容器化平台,允许开发者将应用程序和其依赖项打包成一个可移植的容器,然后部署到任何支持Docker的环境中。然而,在使用Docker构建镜像时,有一个问题是:无法在Dockerfile中使用VOLUME指令来告诉Docker要挂载什么。这是因为这样做会严重破坏容器的可移植性。

VOLUME指令告诉Docker,这些目录中的内容不会被包含在镜像中,可以通过--volumes-from命令行参数从其他容器中访问。要从主机访问这些目录,需要在运行容器时使用-v /path/on/host:/path/in/container参数。

然而,在构建镜像时,无法挂载主机卷。这是由于没有特权构建,并且挂载主机会严重降低容器的可移植性。可以尝试使用wget或curl来下载构建所需的内容,并放置在适当的位置。

有人提出了一个问题,想要在Dockerfile中的构建过程中挂载主机卷到容器中。但是,这是不可能的。尽管这样做可能会破坏容器的可移植性,但有时也有合理的使用场景。例如,分发运行时环境给用户提供的脚本时,可以将当前工作目录挂载到容器中,以保持可移植性。

然而,目前还没有办法避免将构建步骤所需的秘密密钥放入Docker镜像中。这可能会破坏容器的可移植性。

0