如何在Dockerfile中添加大的HTTP文件并将它们从图像层中排除?

我们的Nexus服务器为我们的Java项目(包括其安装程序)提供构build工件。 这个安装程序真的很大 (> 1GB)。 我想检索并在Dockerfile使用它。

我到目前为止所做的是:

 FROM debian:jessie ... RUN apt-get install -y curl xmllib-xpath-perl ENV PROJECT_VERSION xyz-SNAPSHOT ... RUN VERSION=`curl --silent "http://nexus:8081/service/local/artifact/maven/resolve?r=public&g=my.group.id&a=installer&v=${PROJECT_VERSION}&e=sh&c=linux64" | xpath -q -s '' -e '//data/version/text()'` \ && echo Version:\'${VERSION}\' \ && curl --silent http://nexus/content/groups/public/my/group/id/installer/${PROJECT_VERSION}/installer-${VERSION}-linux64.sh \ --create-dirs \ --output ${INSTALL_DIR}/installer.sh \ && sh ${INSTALL_DIR}/installer.sh <someArgs> \ && rm ${INSTALL_DIR}/installer.sh ... 

通过这种方法,我能够:

  • 查询Nexus以提供在docker build期间注销的提供的${PROJECT_VERSION}的最新SNAPSHOT版本
  • 使用该版本下载相应的安装程序二进制文件
  • 执行安装程序二进制文件
  • 在执行后立即删除安装程序二进制文件, 不要将其存储在创build的Docker映像图层中

什么不见​​了:

  • 每当一个新的安装程序被部署到Nexus,我不得不用docker build --no-cache来构buildDocker镜像。 否则,Docker将无法使其caching失效,并重新运行安装步骤,以便同时部署到Nexus的新安装程序。

所以我尝试了使用ADD语句的不同方法,因为那些根据文档具有cachingfunction 。 但这是行不通的,因为我需要提供一个参数给上一步查询正确的SNAPSHOT版本的Nexus查询设置的ADD语句:

 FROM debian:jessie ... RUN apt-get install -y curl xmllib-xpath-perl ENV PROJECT_VERSION xyz-SNAPSHOT ... ADD http://nexus:8081/service/local/artifact/maven/resolve?r=public&g=my.group.id&a=installer&v=${PROJECT_VERSION}&e=sh&c=linux64 ${INSTALL_DIR}/version.xml RUN cat ${INSTALL_DIR}/version.xml | xpath -q -s '' -e '//data/version/text()' > ${INSTALL_DIR}/version.txt # FIXME: Somehow do a `cat ${INSTALL_DIR}/version.txt to set the ENV ${VERSION} variable ?! ADD http://nexus/content/groups/public/my/group/id/installer/${PROJECT_VERSION}/installer-${VERSION}-linux64.sh ${INSTALL_DIR}/installer.sh RUN ${INSTALL_DIR}/installer.sh <someArgs> && rm ${INSTALL_DIR}/installer.sh ... 

这种方法不起作用,因为:

  • 无法将Dockerfile${VERSION}环境variablesDockerfile为存储在version.txt文件中的version.txt
  • 不能防止安装程序存储在图像层中。

但至less这将使用适当的caching来重新使用旧的安装程序版本的现有图像层,并在Nexus上部署新的安装程序版本时创build新的图像层。

所以问题是 :如何同时启用适当的caching,caching失效和从Docker镜像层中排除大安装程序文件?

编辑 :我find了一种方法来获取caching的图像层使用其他Nexus API正常工作:

 FROM debian:jessie ... ENV PROJECT_VERSION xyz-SNAPSHOT ... ADD http://nexus:8081/service/local/artifact/maven/content?r=public&g=my.group.id&a=installer&v=${PROJECT_VERSION}&e=sh&c=linux64 ${INSTALL_DIR}/installer.sh RUN sh ${INSTALL_DIR}/installer.sh <someArgs> \ && rm ${INSTALL_DIR}/installer.sh ... 

但是仍然存在图像层中包含非常大的安装程序文件问题,因为在该代码中,使用了ADD机制。

关于如何从ADD语句提供的caching和正确的无效的任何想法,但同时不包括添加的文件到图像历史?

如何做curl / wget,安装和删除一个长时间的命令?

更新与较小资源的ADD组合,请参阅TC的详细答案。

我接受了Mykola Gurov的回答,因为在他的一个评论中他指出了一个帮助我解决这个问题的想法。

下面是我做了正确的caching和caching失效以及排除大的安装程序文件:

 FROM debian:jessie ... RUN apt-get install -y curl ENV PROJECT_VERSION xyz-SNAPSHOT ... ADD http://nexus:8081/service/local/artifact/maven/resolve?r=public&g=my.group.id&a=installer&v=${PROJECT_VERSION}&e=sh&c=linux64 ${INSTALL_DIR}/installer.xml RUN curl --silent "http://nexus:8081/service/local/artifact/maven/content?r=public&g=my.group.id&a=installer&v=${PROJECT_VERSION}&e=sh&c=linux64" \ --output ${INSTALL_DIR}/installer.sh \ && sh ${INSTALL_DIR}/installer.sh <someArgs> \ && rm ${INSTALL_DIR}/installer.sh ... 

第一个ADD为请求的工件下载Maven元数据。 该XML文件是相当小的。 它使用适当的caching,所以只要Nexus的元数据被修改,caching就会失效。

在这种情况下, ADD和其下面的所有指令都不会重新使用任何caching版本。

如果上次下载后服务器上的元数据没有变化,则执行curlADD和下面的RUN指令将从图像层caching中取出。 而在RUN ,可以一步下载,执行和删除临时大安装程序文件,而不必将其存储在任何图像层中。