Отключить кеш для определенных команд RUN

98

У меня есть несколько RUNкоманд в моем Dockerfile, которые я хотел бы запускать -no-cacheкаждый раз, когда создаю образ Docker.

Я понимаю, что docker build --no-cacheэто отключит кеширование для всего файла Dockerfile.

Можно ли отключить кеш для конкретной команды RUN?

Vingtoft
источник
1
Если после отключения кеша для одной команды результат не соответствует предыдущему кэшированному запуску, вам нужно будет перестроить все оставшиеся шаги. Это ваша цель, или вы надеетесь перестроить только один слой и каким-то образом внедрить его туда, где хранились предыдущие кэшированные данные?
BMitch
2
Я надеялся перестроить определенные слои, например команду «git pull». Сейчас команда «git pull» будет кэширована, даже если репозиторий обновлен.
Vingtoft
2
Достаточно легко вызвать вытягивание, передав неиспользуемый аргумент. Но в результате перестройки этой кэшированной записи потребуется перестройка всех следующих слоев. См. Мой ответ здесь для примера.
BMitch
Если вы хотите сделать кеш недействительным при изменении удаленного git, посмотрите: Как предотвратить кеширование Dockerfile git clone . Вся благодарность @anq за связанный ответ.
hpgmiskin

Ответы:

79

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

Как предлагается в этом комментарии к проблеме , можно добавить блок аргументов сборки (имя может быть произвольным):

ARG CACHEBUST=1 

перед таким регионом и изменяйте его значение при каждом запуске, добавляя --build-arg CACHEBUST=$(date +%s) в качестве docker buildаргумента (значение также может быть произвольным, здесь это текущая дата и время, чтобы гарантировать его уникальность при выполнении).

Это, конечно же, отключит кеш для всех следующих блоков, так как хеш-сумма промежуточного изображения будет другой, что делает действительно выборочное отключение кеша нетривиальной проблемой, учитывая, как в настоящее время работает докер.

Владислав
источник
1
Кажется, больше не работает, просто попал ---> Using cacheпод мою строку `` ARG CACHEBUST = 1` ... (и да, я сделал --build-arg CACHEBUST=$(date +%s)в своей команде докера)
Pylinux
У меня тоже не работает, может это зависит от платформы. Я ожидал, что любое изменение ARG сделает кеш недействительным.
Оливер
6
Вы должны добавить, RUN echo "$CACHEBUST"поскольку простое использование ARGне приведет к аннулированию кеша
Сидхарт V
Этот ответ решил мою проблему здесь: stackoverflow.com/questions/63709147/…
shapiro yaacov
25

Использовать

ADD "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h" skipcache

перед строкой RUN, которую вы хотите всегда запускать. Это работает, потому что ADD всегда будет извлекать файл / URL-адрес, а указанный выше URL-адрес генерирует случайные данные для каждого запроса, затем Docker сравнивает результат, чтобы узнать, может ли он использовать кеш.

Я также протестировал это и отлично работает, поскольку он не требует дополнительных аргументов командной строки Docker, а также работает с файлом Docker-compose.yaml :)

Стив
источник
2
что произойдет, если random.org решит изменить эту конечную точку? как бы вы контролировали такое поведение?
Андрес Леон Рангель,
@AndresLeonRangel По общему признанию, это не функция Docker, а своего рода взлом с использованием синтаксиса Docker и хорошо известной веб-службы, которая существует уже более 20 лет, однако вы правы, говоря, что они могут отказаться от этой конечной точки, фактически просматривая свои документы сейчас Я даже не могу найти конечную точку "randbyte", а у них есть новый API, который сейчас находится в стадии бета-тестирования. Вы можете либо 1) продолжать использовать эту конечную точку, пока она не выйдет из строя, 2) использовать новую конечную точку (пока она не выйдет из строя) или 3) написать свою собственную случайную конечную точку, и в этом случае вы полностью контролируете :)
Стив
2
Иногда это не удавалось ... когда сайт не работает !!! Думаю, это не идеальное решение для этого. Ошибка добавления : не удалось ПОЛУЧИТЬ random.org/cgi-bin/randbyte?nbytes=10&format=h со статусом 503. Служба недоступна: <! DOCTYPE HTML>
Кэти,
1
random.org добавил защиту от DDOS, которая сейчас ломает это решение
Брэд Рут
Это не работает, и данный адрес возвращает 503. Если вы не хотите блокировать конвейеры, не используйте это решение
OlegI
9

Не напрямую, но вы можете разделить свой Dockerfile на несколько частей, построить образ, затем ИЗ этого образа в начале следующего Dockerfile и построить образ с кэшированием или без него.

user2915097
источник
1
Включит ли это обновление зафиксированных слоев в базовом образе докера?
user_mda
7

По состоянию на февраль 2016 года это невозможно.

Функция запрошена на GitHub

Vingtoft
источник
3

функция добавлена ​​неделю назад.

ARG FOO=bar

FROM something
RUN echo "this won't be affected if the value of FOO changes"
ARG FOO
RUN echo "this step will be executed again if the value of FOO changes"

FROM something-else
RUN echo "this won't be affected because this stage doesn't use the FOO build-arg"

https://github.com/moby/moby/issues/1996#issuecomment-550020843

Тха саами
источник
0

Я считаю, что это небольшое улучшение по сравнению с ответом @stve выше:

RUN git clone https://sdk.ghwl;erjnv;wekrv;qlk@gitlab.com/your_name/your_repository.git

WORKDIR your_repository

# Calls for a random number to break the cahing of the git clone
# (/programming/35134713/disable-cache-for-specific-run-commands/58801213#58801213)
ADD "https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h" skipcache
RUN git pull

Это использует кеш Docker клона git, но затем запускает некэшированное обновление репозитория.

Он появляется на работу, и это быстрее - но многие благодаря @steve для обеспечения основополагающих принципов.

Майк Сэдлер
источник
-2

Еще один быстрый прием - написать несколько случайных байтов перед вашей командой.

RUN head -c 5 /dev/random > random_bytes && <run your command>

записывает 5 случайных байтов, что приведет к пропуску кеша

отметка
источник
10
Результат записи этих случайных байтов также кэшируется, поэтому, если до этой команды не было изменено ни одного файла, он не будет запускать команду снова. Это ничего не решает.
Icy Defiance