docker - 为什么每次我更改构建参数时 docker 都会重建所有层
问题描述
我有一个包含很多层的 docker 文件。在文件的顶部,我有一些参数,例如
FROM ubuntu:18.04
ARGS USER=test-user
ARGS UID=1000
#ARGS PW=test-user
# Then several Layers which does not use any ARGS. Example
LABEL version="1.0"
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
RUN mkdir ~/mapped-volume
RUN apt-get update && apt-get install -y wget bzip2 ca-certificates build-essential curl git-core htop pkg-config unzip unrar tree freetds-dev vim \
sudo nodejs npm net-tools flex perl automake bison libtool byacc
# And so on
# And finally towards the end
# Setup User
RUN useradd -m -d /home/${USER} --uid ${UID} -G sudo -s /bin/bash ${USER}
# && echo "${USER}:${PW}" | chpasswd
# Couple of more commands to change dir, entry point etc. Example
当我使用与上次构建不同的任何 arg 值和/或在最后两层中进行微小更改后构建此 docker 文件时,构建将再次构建所有内容。它不使用缓存层。我用来构建的命令是这样的
docker build --build-arg USER=new-user --build-arg UID=$UID -t my-image:1.0 .
每次我更改值时,构建都会再次进行。带有如下截断的顶部
UID -t my-image:1.0 .
Sending build context to Docker daemon 44.54kB
Step 1/23 : FROM ubuntu:18.04
---> ccc6e87d482b
Step 2/23 : ARG USER=ml-user
---> Using cache
---> 6c0c5d5c5056
Step 3/23 : ARG UID=1000
---> Using cache
---> b25867c282c7
Step 4/23 : LABEL version="1.0"
---> Running in 1ffff70d56c1
Removing intermediate container 1ffff70d56c1
---> 0f1277def3ca
Step 5/23 : ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
---> Running in 49d08c41b233
Removing intermediate container 49d08c41b233
---> f5b345573c1f
Step 6/23 : RUN mkdir ~/mapped-volume
---> Running in e4f8a5956450
Removing intermediate container e4f8a5956450
---> 1b22731d9051
Step 7/23 : RUN apt-get update && apt-get install -y wget bzip2 ca-certificates build-essential curl git-core htop pkg-config unzip unrar tree freetds-dev vim sudo nodejs npm net-tools flex perl automake bison libtool byacc
---> Running in ffc297de6234
Get:1 http://archive.ubuntu.com/ubuntu bionic InRelease [242 kB]
所以从第 7 步开始,它一直在执行所有步骤,而不使用应该有一堆包的那个层的缓存 为什么?我怎样才能阻止这个?以前我没有 args 的时候,这个层和其他层过去都是从缓存中提取的。
解决方案
将您的 args 移动到您需要它们之前。Docker 在运行命令之前不会替换 RUN 命令中的 args。相反,args 作为环境变量传递,并由临时容器内的 shell 扩展。因此,对 arg 的更改就是对环境的更改,并且错过了该步骤的构建缓存。一旦一个步骤错过了缓存,必须重建所有后续步骤。
FROM ubuntu:18.04
# Then several Layers which does not use any ARGS. Example
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
RUN mkdir ~/mapped-volume
RUN apt-get update && apt-get install -y wget bzip2 ca-certificates build-essential curl git-core htop pkg-config unzip unrar tree freetds-dev vim \
sudo nodejs npm net-tools flex perl automake bison libtool byacc
# And so on
# And finally towards the end
# Setup User
ARGS USER=test-user
ARGS UID=1000
RUN useradd -m -d /home/${USER} --uid ${UID} -G sudo -s /bin/bash ${USER}
# && echo "${USER}:${PW}" | chpasswd
# Couple of more commands to change dir, entry point etc. Example
LABEL version="1.0"
此外,在构建时不需要的标签、环境变量、暴露的端口和任何其他元数据通常最好留在 Dockerfile 的末尾,因为它们对构建时间的影响最小,并且不需要错过缓存他们改变了。
推荐阅读
- python - 如何将 postgresql 日期时间更改为字符串?
- java - Java 中的异常处理 - 继续执行,直到用户输入四个有效的员工 ID
- javascript - 我的 javascript 代码不会将元素推送到我的数组中,我不知道为什么?
- algorithm - 如何将有限的糖果分配给孩子们?
- python - 如何在json文件数组python中添加数据
- php - 当我尝试在 html 中回显时,为什么我的 file_get_contents 函数会导致图像损坏?
- c - 如何在 C 中接受文件并生成存档文件?
- python - 迁移学习:模型给出不变的损失结果。不是训练吗?
- android - 我正在尝试替换 Android 应用程序中的片段,但我的片段没有改变(Kotlin)
- azure-devops - 仓促重建指定项目顺序