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

h3n*_*rik 5 curl nexus docker dockerfile

我们的Nexus 服务器为我们的 Java 项目提供构建工件,包括其安装程序。该安装程序非常大(> 1GB)。我想检索并在Dockerfile.

到目前为止,我所做的如下:

FROM debian:jessie
...
RUN apt-get install -y curl xmllib-xpath-perl
ENV PROJECT_VERSION x.y.z-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
...
Run Code Online (Sandbox Code Playgroud)

通过这种方法,我能够:

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

有什么不见了:

  • 每当将新安装程序部署到 Nexus 时,我都必须使用docker build --no-cache. 否则 Docker 无法使其缓存失效并为同时部署到 Nexus 的较新安装程序重新运行安装步骤。

所以我尝试了一种使用该ADD语句的不同方法,因为它们根据文档具有缓存功能。但这不起作用,因为我需要为ADD上一步查询 Nexus 以获取正确 SNAPSHOT 版本的语句提供一个参数:

FROM debian:jessie
...
RUN apt-get install -y curl xmllib-xpath-perl
ENV PROJECT_VERSION x.y.z-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
...
Run Code Online (Sandbox Code Playgroud)

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

  • 无法将 中的${VERSION}环境变量设置Dockerfileversion.txt文件中存储的版本。
  • 无法阻止将安装程序存储在映像层中。

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

所以问题是:如何同时从 Docker 镜像层启用正确的缓存、缓存失效和排除大安装程序文件?

编辑:我找到了一种通过使用其他 Nexus API 使图像层缓存正常工作的方法:

FROM debian:jessie
...
ENV PROJECT_VERSION x.y.z-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
...
Run Code Online (Sandbox Code Playgroud)

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

关于如何从ADD语句提供的缓存及其正确失效中受益但同时不将添加的文件包含到图像历史记录中的任何想法?

Myk*_*rov 0

在一个长时间运行的命令中执行curl/wget、安装和删除怎么样?

结合ADD较小的资源进行更新,请参阅TC的详细答案。