Как заставить Docker для чистой сборки образа

819

Я построил образ Docker из файла Docker с помощью приведенной ниже команды.

$ docker build -t u12_core -f u12_core .

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

Step 1 : FROM ubuntu:12.04
 ---> eb965dfb09d2
Step 2 : MAINTAINER Pavan Gupta <pavan.gupta@gmail.com>
 ---> 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 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -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

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

Паван Гупта
источник
10
Кроме того, вы должны стараться свести к минимуму количество RUNдиректив.
tripleee
4
@tripleee Можете ли вы объяснить, почему?
Я.
9
@Ya. Раньше Docker всегда создавал отдельный слой для каждой RUNдирективы, поэтому Dockerfileсо многими RUNдирективами потребовалось бы огромное количество дискового пространства; но это, по-видимому, несколько улучшилось в последних версиях.
tripleee
Когда я пытаюсь docker-compose up -d, где я могу использовать --no-cache?
Оо
1
@ Ну, это невозможно. Сначала нужно сделать, docker-compose build --no-cacheа потомdocker-compose up -d
Мартин Мелка

Ответы:

1446

Там есть --no-cacheвариант:

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

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

Ассаф Лави
источник
89
Также обратите внимание, что --no-cacheработает с docker-compose build.
Blackus
42
Вы также можете использовать --pull. Это скажет докеру получить последнюю версию базового образа. Это необходимо в дополнение к тому, --no-cacheесли у вас уже есть базовый образ (например, ubuntu/latest), и базовый образ был обновлен с момента последнего его извлечения. Смотрите документы здесь .
Коллин Кроулл
2
@CollinKrawll: --pullвариант сделал свое дело для меня. Просто --no-cache, сборка еще сломалась. Положите, --pullа построить работает! Спасибо!
Erdős-Bacon
1
Если кто-то вызывает сборку Docker, разве не предполагается, что он хочет восстановить без кеша? В каком случае кто-то захочет создать изображение и использовать ранее созданное изображение? <rant> Я только что потерял день, потому что предыдущая сборка завершилась неудачно, но завершилась «успешно», и я использовал сломанное изображение, не понимая, почему не работали обновления для скрипта сборки </ rant>
Джефф
3
@Jeff Когда вы разрабатываете образ докера, сборка докера будет только возвращать измененные слои / шаги. Если у меня есть пять шагов, и я добавляю новый шаг с индексом 3, слои, связанные с шагами 1 и 2, можно использовать повторно. Это значительно ускоряет процесс разработки
хлопья
130

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

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]

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

Уоллес Сидре
источник
8
добавление -a -f делает его лучше
Рави
1
@IulianOnofrei работает для меня,Docker version 17.09.0-ce, build afdb6d4
Per Lundberg
1
@PerLundberg, я обновился dockerдо той же версии, и она работает, спасибо.
Юлиан
1
Это слишком избыточно для этого сценария, а не пригодный для использования ответ, если вы не хотите удалять все.
M_dk
1
Это даже приведет к удалению изображений остановленных контейнеров, вероятно, того, что вам не нужно. В последних версиях Docker есть команда docker builder pruneдля очистки кэшированных слоев сборки. Просто попал в ловушку после слепого копирования команд из переполнения стека.
Злой Азраэль
59

Команда 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

Для предотвращения кеширования обновления и установки отдельно.

Смотрите: Лучшие практики для написания Dockerfiles

Youniteus
источник
10
«Должен был» вводит в заблуждение. Если Docker увидит, что у него есть кэшированная копия, RUN apt-get update && apt-get -y install php5-fpmвы все равно увидите, что он снова используется со старым содержимым.
tripleee
10
На самом деле все же имеет смысл присоединиться к ним, потому что в противном случае, если вы измените строку установки, он все равно будет использовать кеш старого пакета, который часто будет иметь проблемы, если кеш устарел (обычно файлы будут 404.)
Джон Чедвик
19

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

--no-cache - Это приведет к восстановлению уже доступных слоев

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

Поэтому полная команда будет выглядеть так:

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

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

docker-compose build --no-cache --pull
M_dk
источник
13

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

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

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

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

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

Оливье
источник
3
Способность быть в состоянии не использовать кэш после определенного момента это функция по просьбе многих (см github.com/moby/moby/issues/1996 альтернатив для очистки кэша)
leszek.hanusz
13

С docker-compose попробуй docker-compose up -d --build --force-recreate

Яши
источник
6

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

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

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

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) Протрите кэш Docker Builder (если мы используем Buildkit, нам, вероятно, это нужно):

docker builder prune -af

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

docker image rm -f fooParentImage

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

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

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

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

docker image prune -a

2) Удалить еще много вещей:

docker system prune -a

Это говорит:

ПРЕДУПРЕЖДЕНИЕ! Это удалит:
  - все остановленные контейнеры
  - все сети не используются хотя бы одним контейнером
  - все изображения без как минимум одного связанного с ними контейнера
  - весь кеш сборки

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

davidxxx
источник
3

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

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

Шон
источник