我构建了一个映像,它有一个 RUN 阶段,只加载包,另一个阶段之后进行一些初始化。如果我立即重建,它会按应有的方式使用缓存进行阶段。对于稍后的初始化 RUN 阶段,我设置了一个“手动破坏”。如果我在那时“破坏”,那么它会使用缓存进行所有前面的阶段。它按预期正常工作。
但
如果我在容器中使用该镜像,然后返回并构建镜像,则整个缓存将被破坏,整个镜像将被重建。我希望这种情况不会发生,因为软件包安装花费的时间最长,并且不需要一次又一次地安装。
简而言之,我想测试图像,如果有问题,则仅重建最后的初始化运行阶段,而不是安装包的阶段,但是一旦我使用图像,整个缓存就会被破坏。
为什么会发生这种情况?有没有办法使用图像但保留构建缓存?我想知道为什么在容器中运行图像与构建缓存有什么关系?
ARG BASE_IMAGE
FROM $BASE_IMAGE
ARG BASE_IMAGE
ARG KEEP
ARG SYSADMIN_PW
ARG LINUX_DISTRO=alpine
ARG BUILD_DIR=/build
WORKDIR $BUILD_DIR
COPY .src ./
# PACKAGES
RUN echo -e "\n ************************************************* \n"\
echo "****** Building Image from Base: $BASE_IMAGE; : Distro: $LINUX_DISTRO; *****"; \
echo " ---- running packages install script ---"; /bin/sh ./packages.sh; \
echo -e "\n********************************************************"
# END PACKAGES
ARG BUST_INIT_CACHE
# INITIALIZATION
RUN echo -e "\n ************************************************* \n" \
echo "****** BUST_INIT_CACHE ${BUST_INIT_CACHE} "; \
echo "****** Running Initialization Script "; \
chmod -R +x .; \
pwd; ls -la; \
echo " ---- running init script ---"; /bin/bash ./init.sh; \
echo -e "\n********************************************************"
# END INITIALIZATION
VOLUME [ "/data", "/opt", "/shell" ]
WORKDIR /opt
# ENTRYPOINT ["entrypoint.sh"]
CMD ["/bin/bash", "-l"]
答案1
docker 论坛上的一个帖子就是线索。问题出在 copy 命令上。我在 copy 语句中使缓存无效。
我需要两个复制语句。我需要通过它们自己的子文件夹复制包和初始化脚本。这样,如果我在初始化脚本子文件夹中更改了某些内容,包复制命令就不会失效。
这也解决了运行容器和使缓存无效的问题。附带的好处是现在我不需要手动清除缓存,因为只需更改 init 脚本文件夹中的任何内容即可。
COPY .src/packages ./packages
# PACKAGES
RUN \
echo -e "\n ************************************************* \n"\
echo "****** Building Image from Base: $BASE_IMAGE; : Distro: $LINUX_DISTRO; *****"; \
echo " ---- running packages install script ---"; /bin/sh ./packages/packages.sh; \
echo -e "\n********************************************************"
# END PACKAGES
COPY .src/init ./init
# INITIALIZATION
RUN echo -e "\n ************************************************* \n" \
echo "****** Running Initialization Script "; \
chmod -R +x .; \
pwd; ls -la; \
echo " ---- running init script ---"; /bin/bash ./init/init.sh; \
echo -e "\n********************************************************"
# END INITIALIZATION