Как заставить Docker выполнить чистую сборку образа

1124

Я создал образ Docker из файла Docker, используя следующую команду.

$ docker build -t u12_core -f u12_core .

Когда я пытаюсь восстановить его с помощью той же команды, он использует кеш сборки, например:

Step 1 : FROM ubuntu:12.04
 ---> eb965dfb09d2
Step 2 : MAINTAINER Pavan Gupta <[email protected]>
 ---> Using cache
 ---> 4354ccf9dcd8
Step 3 : RUN apt-get update
 ---> Using cache
 ---> bcbca2fcf204
Step 4 : RUN apt-get install -y openjdk-7-jdk
 ---> Using cache
 ---> 103f1a261d44
Step 5 : RUN apt-get install -y openssh-server
 ---> Using cache
 ---> dde41f8d0904
Step 6 : RUN apt-get install -y git-core
 ---> Using cache
 ---> 9be002f08b6a
Step 7 : RUN apt-get install -y build-essential
 ---> Using cache
 ---> a752fd73a698
Step 8 : RUN apt-get install -y logrotate
 ---> Using cache
 ---> 93bca09b509d
Step 9 : RUN apt-get install -y lsb-release
 ---> Using cache
 ---> fd4d10cf18bc
Step 10 : RUN mkdir /var/run/sshd
 ---> Using cache
 ---> 63b4ecc39ff0
Step 11 : RUN echo 'root:root' | chpasswd
 ---> Using cache
 ---> 9532e31518a6
Step 12 : RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
 ---> Using cache
 ---> 47d1660bd544
Step 13 : RUN sed '[email protected]\s*required\s*[email protected] optional [email protected]' -i /etc/pam.d/sshd
 ---> Using cache
 ---> d1f97f1c52f7
Step 14 : RUN wget -O aerospike.tgz 'http://aerospike.com/download/server/latest/artifact/ubuntu12'
 ---> Using cache
 ---> bd7dde7a98b9
Step 15 : RUN tar -xvf aerospike.tgz
 ---> Using cache
 ---> 54adaa09921f
Step 16 : RUN dpkg -i aerospike-server-community-*/*.deb
 ---> Using cache
 ---> 11aba013eea5
Step 17 : EXPOSE 22 3000 3001 3002 3003
 ---> Using cache
 ---> e33aaa78a931
Step 18 : CMD /usr/sbin/sshd -D
 ---> Using cache
 ---> 25f5fe70fa84
Successfully built 25f5fe70fa84

Кеш показывает, что установлен aerospike. Однако я не нахожу его внутри контейнеров, созданных из этого изображения, поэтому я хочу перестроить этот образ без использования кеша. Как заставить Docker восстановить чистый образ без кеша?

6
  • 20
    Кроме того, вы должны стараться минимизировать количество RUNдиректив. tripleee 27 сен.
  • 9
    @tripleee Вы можете объяснить почему? Ya. 20 фев '19 в 16:59
  • 17
    @Я. Раньше Docker всегда создавал отдельный слой для каждой RUNдирективы, поэтому для Dockerfileмногих RUNдиректив требовалось огромное количество дискового пространства; но это, по-видимому, было несколько улучшено в последних версиях. tripleee 20 фев '19 в 17:02
  • Когда я попробую docker-compose up -d, где я могу использовать --no-cache? Plum 29 янв.
  • 6
    @Oo это невозможно. Сначала надо сделать, docker-compose build --no-cacheа потомdocker-compose up -dMartin Melka 5 мая '20 в 8:40
1929

Есть --no-cacheвариант:

docker build --no-cache -t u12_core -f u12_core .

В более старых версиях Docker вам нужно было пройти --no-cache=true, но это уже не так.

6
  • 141
    Также обратите внимание, что --no-cacheработает с docker-compose build. Blackus 25 авг.
  • 66
    Вы также можете использовать --pull. Это сообщит докеру, что нужно загрузить последнюю версию базового образа. Это необходимо в дополнение к тому, --no-cacheесли у вас уже есть базовое изображение (например:), ubuntu/latestи базовое изображение было обновлено с тех пор, как вы его в последний раз загрузили. Смотрите документацию здесь . Collin Krawll 19 дек '18 в 20:39
  • 7
    @CollinKrawll: Этот --pullвариант помог мне. Просто --no-cacheсборка все равно сломалась. Вставил --pullтоже, сборка заработала! Спасибо! Erdős-Bacon 5 апр '19 в 22:04
  • 1
    Если кто-то вызывает сборку докеров, разве не предполагается, что они хотят перестроить без кеша? В каком варианте использования кто-то захочет создать образ и использовать ранее созданный образ? <rant> Я только что потерял день, потому что предыдущая сборка не удалась, но завершилась «успешно», и я использовал сломанный образ, не понимая, почему обновления сценария сборки не работают </rant>Jeff 24 мая '19 в 19:46
  • 4
    @Jeff Когда вы разрабатываете образ докера, сборка докера будет повторять только те слои / шаги, которые были изменены. Если у меня есть пять шагов, и я добавляю новый шаг с индексом 3, слои, связанные с шагами 1 и 2, можно использовать повторно. Это значительно ускоряет процесс разработкиflakes 8 авг.
163

В некоторых крайних случаях единственный способ обойти повторяющиеся сбои сборки - это запустить:

docker system prune

Команда запросит у вас подтверждение:

WARNING! This will remove:
    - all stopped containers
    - all volumes not used by at least one container
    - all networks not used by at least one container
    - all images without at least one container associated to them
Are you sure you want to continue? [y/N]

Это, конечно, не прямой ответ на вопрос, но может спасти несколько жизней ... Это спасло мою.

7
  • 9
    добавление -a -f делает его лучшеRavi 4 окт.
  • 1
    @IulianOnofrei У меня работает,Docker version 17.09.0-ce, build afdb6d4Per Lundberg 23 ноя '17 в 10:10
  • 1
    @PerLundberg, я обновился dockerдо той же версии, и она работает, спасибо. Iulian Onofrei 23 ноя '17 в 13: 132017-11-23 10:13
  • 3
    Это слишком много для этого сценария и не подходит, если вы не хотите удалять все. M_dk 26 сен '19 в 11:16
  • 8
    Это даже приведет к удалению изображений остановленных контейнеров, что, вероятно, вам не нужно. В последних версиях docker есть команда docker builder pruneдля очистки кешированных слоев сборки. Просто попал в ловушку после слепого копирования команд из переполнения стека. Evil Azrael 24 ноя '19 в 17:31
70

Команда docker build --no-cache .решила нашу аналогичную проблему.

Наш Dockerfile был:

RUN apt-get update
RUN apt-get -y install php5-fpm

Но должно было быть:

RUN apt-get update && apt-get -y install php5-fpm

Чтобы не кешировать обновление и устанавливать отдельно.

См .: Рекомендации по написанию файлов Dockerfile.

2
  • 11
    Выражение «должно было быть» вводит в заблуждение. Если Docker увидит, что у него есть кешированная копия, RUN apt-get update && apt-get -y install php5-fpmвы все равно увидите, что он повторно используется со старым содержимым. tripleee 27 сен.
  • 11
    На самом деле все еще имеет смысл присоединиться к ним, потому что в противном случае, если вы измените строку установки, он все равно будет использовать старый кеш пакетов, который часто будет иметь проблемы, если кеш устарел (обычно файлы будут 404.)John Chadwick 24 янв.
61

Чтобы убедиться, что ваша сборка полностью перестроена, включая проверку базового образа на наличие обновлений, используйте следующие параметры при сборке:

--no-cache - Это заставит перестроить уже доступные слои

--pull - Это вызовет загрузку базового образа, на который ссылается FROM, чтобы убедиться, что у вас установлена ​​последняя версия.

Таким образом, полная команда будет выглядеть так:

docker build --pull --no-cache --tag myimage:version .

Те же параметры доступны для docker-compose:

docker-compose build --no-cache --pull

Обратите внимание, что если ваш файл docker-compose ссылается на изображение, опция --pull фактически не будет извлекать изображение, если оно уже есть.

Чтобы заставить docker-compose повторно вытащить это, вы можете запустить:

docker-compose pull
1
26

Большая часть информации здесь верна.
Вот их подборка и мой способ их использования.

Идея состоит в том, чтобы придерживаться рекомендованного подхода (специфичный для сборки и не влиять на другие сохраненные объекты докеров) и пробовать более радикальный подход (не специфичный для сборки и влияющий на другие сохраненные объекты докеров), когда этого недостаточно.

Рекомендуемый подход:

1) Принудительное выполнение каждого шага / инструкции в Dockerfile:

docker build --no-cache 

или с docker-compose build:

docker-compose build --no-cache

Мы также можем объединить это с upподкомандой, которая воссоздает все контейнеры:

docker-compose build --no-cache &&
docker-compose up -d --force-recreate 

В этом случае не используется кеш, кроме конструктора докеров и базового образа, на который ссылается FROMинструкция.

2) Протрите кеш построителя докеров (если мы используем Buildkit, он нам, скорее всего, понадобится):

docker builder prune -af

3) Если мы не хотим использовать кеш родительских изображений, мы можем попытаться удалить их, например:

docker image rm -f fooParentImage

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

Более радикальный подход:

В крайних случаях, когда кажется, что некоторые объекты в кэше докеров все еще используются во время сборки и это выглядит повторяемым, мы должны попытаться понять причину, чтобы иметь возможность стереть недостающую часть очень конкретно. Если мы действительно не найдем способ восстановить с нуля, есть другие способы, но важно помнить, что они обычно удаляют гораздо больше, чем требуется. Поэтому мы должны использовать их с осторожностью в целом, когда мы не находимся в локальной среде / dev.

1) Удалите все изображения без связанного с ними хотя бы одного контейнера:

docker image prune -a

2) Убрать еще много чего:

docker system prune -a

Это говорит:

WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all images without at least one container associated to them
  - all build cache

Использование этой команды super delete может быть недостаточно, потому что она сильно зависит от состояния контейнеров (запущены или нет). Когда этой команды недостаточно, я стараюсь тщательно продумать, какие контейнеры докеров могут вызвать побочные эффекты для нашей сборки докеров, и разрешить выход из этих контейнеров, чтобы их можно было удалить с помощью команды.

1
  • docker image prune (без -a) более дружелюбен и не уничтожит все ваши изображения, которые вы можете захотеть. java-addict301 3 июня в 7:07
23

С помощью docker-compose попробуйте docker-compose up -d --build --force-recreate

1
  • у меня не сработалоjava-addict301 3 июня в 7:02
16

Я бы не рекомендовал использовать --no-cacheв вашем случае.

Вы запускаете пару установок с шагов 3 по 9 (я бы, кстати, предпочел бы использовать один лайнер), и если вы не хотите, чтобы накладные расходы на повторный запуск этих шагов каждый раз, когда вы строите свой образ, вы можете измените ваш Dockerfileс помощью временного шага до вашей wgetинструкции.

Я использую, чтобы сделать что-то вроде RUN ls .и изменить его на RUN ls ./то RUN ls ./.и так далее для каждой модификации, сделанной в архиве, полученном с помощьюwget

Конечно, вы можете сделать что-то вроде RUN echo 'test1' > test && rm testувеличения числа 'test1для каждой итерации.

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

1
  • 4
    Возможность не использовать кеш после определенного момента - это функция, которую многие просят (см. Github.com/moby/moby/issues/1996 для альтернатив для очистки кеша)leszek.hanusz 13 ноя '18 в 7:31
2

Вы можете управлять кешем построителя с помощью docker builder

Чтобы очистить весь кеш без запроса: docker builder prune -af

1
  • OP не использует buildkituser3710044 18 авг.
0

Подход, основанный на графическом интерфейсе: откройте инструмент рабочего стола Docker (который обычно входит в состав Docker):

  1. в разделе «Контейнеры / приложения» остановите все запущенные экземпляры этого образа.
  2. в разделе «Изображения» удалите образ сборки (наведите указатель мыши на имя поля, чтобы открыть контекстное меню), в конечном итоге также и базовое изображение.