Помещает ли ARG поверх Dockerfile предотвращать повторное использование слоя?

Если ARG, объявленный в верхней части файла Dockerfile, будет изменен, но его значение используется только для команды RUN в конце файла Docker, делает ли Docker перекомпиляцию всего изображения с нуля или может ли он повторно использовать, используйте промежуточное изображение справа перед соответствующей командой RUN?

Чтобы лучше использовать слоирование, следует ли размещать объявления ARG в верхней части файла Docker или непосредственно перед секцией, которая их использует?

Я предполагаю, что часть моего вопроса заключается в том, генерирует ли директива ARG промежуточный уровень.

Ответ 1

Если вы измените значение аргумента построения всех слоев после того, как строка ARG окажется недействительной. Поэтому я думаю, вы должны включить его непосредственно перед использованием ARG.

Перед тем, как он вам понадобится:

 docker build --build-arg TEST_ARG=test .
 Sending build context to Docker daemon 2.048 kB
 Step 1 : FROM ubuntu
 ---> 104bec311bcd
 Step 2 : RUN echo "no arg used"
 ---> Using cache
 ---> 5c29cb363a27
 Step 3 : ARG TEST_ARG
 ---> Using cache
 ---> 73b6080f973b
 Step 4 : RUN echo $TEST_ARG
 ---> 0acd55c24441
 Successfully built 0acd55c24441

В верхней части:

docker build --build-arg TEST_ARG=test .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM ubuntu
 ---> 104bec311bcd
Step 2 : ARG TEST_ARG
---> Using cache
---> b611a1023fe3
Step 3 : RUN echo "no arg used"
---> Running in 63e0f803c6b2
no arg used
---> 592311ccad72
Removing intermediate container 63e0f803c6b2
Step 4 : RUN echo $TEST_ARG
---> Running in 1515aa8702f0
test
---> fc2d850fbbeb
Removing intermediate container 1515aa8702f0
Successfully built fc2d850fbbeb

В первом примере из кэша используются два слоя, а во втором - только один слой (как ни странно, сам слой ARG) используется из кеша.

Ответ 2

Чтобы быть более точным, чем принятый ответ, не все строки кэшируются недействительными после объявления ARG. Только те, которые используют значения ARG и RUN. Документация докера была изменена для обработки недействительности кэша ARG: https://github.com/moby/moby/issues/18017 и https://github.com/moby/moby/pull/18161, а затем более точно с объяснением RUN здесь https://github.com/moby/moby/pull/21885 и официальный документ https://docs.docker.com/engine/reference/builder/#impact-on-build-caching:

Влияние цитаты на кэширование сборки Переменные ARG не сохраняются во встроенном образе, как переменные ENV. Однако переменные ARG влияют на кеш сборки аналогичным образом. Если Dockerfile определяет переменную ARG, значение которой отличается от предыдущей сборки, то при первом использовании происходит "пропадание кэша", а не его определение. В частности, все инструкции RUN, следующие за инструкцией ARG, неявно используют переменную ARG (как переменную среды), что может привести к пропаданию кэша. Все предопределенные переменные ARG освобождаются от кэширования, если в Dockerfile отсутствует соответствующий оператор ARG.

Так что да, я полагаю, вам нужно будет переместить свои аргументы под номерами RUN, которые не нуждаются в аргументе, чтобы оптимизировать кэш слоя.