如何在不使用ADD或COPY指令的情况下将文件添加到Dockerfile中的图像

我需要在我的Docker容器中的一个大的*.zip文件(5 GB)的内容,以编译一个程序。 *.zip文件驻留在本地机器上。 这个战略是:

 COPY program.zip /tmp/ RUN cd /tmp \ && unzip program.zip \ && make 

完成这个之后,我想删除解压后的目录和原始的*.zip文件,因为它们不再需要。 问题是, COPY (也是ADD指令)将添加一个图层,该图像将包含文件program.zip是有问题的,因为可能图像将至less5GB大。 有没有办法将文件添加到容器,而不使用COPYADD指令? wget将无法正常工作,因为提到的*.zip文件位于本地计算机上, curl file://localhost/home/user/program.zip -o /tmp/program.zip也不起作用。

这不是直截了当的,但可以通过wget或者使用python的一点支持来完成。 (所有这三个工具通常应该在*nix系统上可用。)

没有url时, wget将不起作用

  curl file://localhost/home/user/program.zip -o /tmp/ 

将不会在DockerfileRUN指令中工作。 因此,我们需要一个wgetcurl可以访问和下载program.zip的服务器。

为了做到这一点,我们build立了一个小型的python服务器来服务我们的http请求。 我们将使用pythonhttp.server模块进行此操作。 (你可以使用pythonpython 3 ,它可以同时使用)。

 python -m http.server --bind 192.168.178.20 8000 

python服务器将提供它所在的目录中的所有文件。所以你应该确保你启动你的服务器或者在图像编译期间要下载的文件的目录中,或者创build一个包含你的程序的临时目录。 为了便于说明,我们创build一个文件foo.txt ,稍后我们将通过wgetDockerfile下载这个文件:

 echo "foo bar" > foo.txt 

启动http服务器时,重要的是我们在局域网上指定本地计算机的IP地址。 此外,我们将打开端口8000.完成这个,我们应该看到以下输出:

 python3 -m http.server --bind 192.168.178.20 8000 Serving HTTP on 192.168.178.20 port 8000 ... 

现在我们构build一个Dockerfile来说明这是如何工作的。 (我们将假设文件foo.txt应该被下载到/tmp ):

 FROM debian:latest RUN apt-get update -qq \ && apt-get install -y wget RUN cd /tmp \ && wget http://192.168.178.20:8000/foo.txt 

现在我们开始构build

 docker build -t test . 

在构build期间,您将在我们的python服务器上看到以下输出:

 172.17.0.21 - - [01/Nov/2014 23:32:37] "GET /foo.txt HTTP/1.1" 200 - 

我们的图像的构build输出将是:

 Step 2 : RUN cd /tmp && wget http://192.168.178.20:8000/foo.txt ---> Running in 49c10e0057d5 --2014-11-01 22:56:15-- http://192.168.178.20:8000/foo.txt Connecting to 192.168.178.20:8000... connected. HTTP request sent, awaiting response... 200 OK Length: 25872 (25K) [text/plain] Saving to: `foo.txt' 0K .......... .......... ..... 100% 129M=0s 2014-11-01 22:56:15 (129 MB/s) - `foo.txt' saved [25872/25872] ---> 5228517c8641 Removing intermediate container 49c10e0057d5 Successfully built 5228517c8641 

然后,您可以通过从刚刚构build的映像启动并input容器来检查它是否真正起作用:

 docker run -i -t --rm test bash 

然后可以在/tmp查找foo.txt

我们现在可以添加任何文件到我们的image而无需创build一个新图层。 假设你想添加一个约5 GB的程序,如问题中提到的,我们可以这样做:

 FROM debian:latest RUN apt-get update -qq \ && apt-get install -y wget RUN cd /tmp \ && wget http://conventiont:8000/program.zip \ && unzip program.zip \ && cd program \ && make \ && make install \ && cd /tmp \ && rm -f program.zip \ && rm -rf program 

这样我们就不会剩下10克。

你能不能映射一个本地文件夹到启动时的容器,然后复制你需要的文件。

 sudo docker run -d -P --name myContainerName -v /localpath/zip_extract:/container/path/ yourContainerID 

https://docs.docker.com/userguide/dockervolumes/

没有办法做到这一点。 function请求在这里https://github.com/docker/docker/issues/3156

我在这里发布了类似的答案: https : //stackoverflow.com/a/37542913/909579

您可以使用docker-squash来挤压新创build的图层。 如果在后续的RUN指令中删除档案,这将会从最终映像中删除档案。