Кэширование билдов Docker

0
260
views

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

В этом руководстве мы разберем, как с толком использовать кэш docker build.

Кэш docker build

Сборка образов должна быть быстрой, эффективной и надежной. Концепция образов Docker связана с неизменяемостью слоев. Каждая команда, которую вы выполняете, создает новый слой, содержащий изменения, которых нет в предыдущем слое.

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

Как с толком использовать кэш docker build

Чтобы понять, какие проблемы могут быть связаны с кэшем, давайте соберем простое Docker-приложение с собственным nginx. Прежде чем собрать образ, создаем Dockerfile для обновления библиотек и добавления своей стартовой страницы.

FROM nginx:1.21.6

# Update all packages
RUN apt-get update && apt-get -y upgrade

# Use a custom startpage
RUN echo '<html><bod>My Custom Startpage</body></html>' > /usr/share/nginx/html/index.html

Теперь можно собрать образ Docker:

$  docker build -t my-custom-nginx .

=> [1/3] FROM docker.io/library/nginx:1.21.6@sha256:e12...  5.8s
=> [2/3] RUN apt-get update && apt-get -y upgrade           3.6s
=> [3/3] RUN echo '<html><bod>My Custom Startpage...        0.2s

=> exporting to image                                       0.1s
=> exporting layers                                         0.1s
=> writing image                                            0.0s
=> naming to docker.io/library/my-custom-nginx

[+] Building 11.3s (7/7) FINISHED

В этом примере я удалил часть вывода для лучшей читаемости. Первая сборка образа занимает какое-то время, в моем случае она длилась 11,3 с.

Самый затратный по времени шаг — apt-get update && apt-get -y upgrade. Длительность его выполнения зависит от того, сколько зависимостей обновляется и насколько шустрый у вас интернет. Эта команда проверяет, есть ли обновления для пакетов, имеющихся в операционной системе, и, если таковые доступны, устанавливает их.

Если вы запустите сборку снова, вы почувствуете пользу кэша docker build.

$ docker build -t my-custom-nginx .

=> [1/3] FROM docker.io/library/nginx:1.21.6@sha256:e1211ac1…   0.0s
=> CACHED [2/3] RUN apt-get update && apt-get -y upgrade        0.0s
=> CACHED [3/3] RUN echo '<html><bod>My Custom Startpage...     0.0s

=> exporting to image                                           0.0s
=> exporting layers                                             0.0s
=> writing image                                                0.0s
=> naming to docker.io/library/my-custom-nginx

Building 1.1s (7/7) FINISHED

На этот раз сборка произошла очень быстро, потому что docker build может использовать заново все образы, собранные ранее.

Изменив стартовую страницу в Dockerfile, вы увидите, как это скажется на использовании кэша:

FROM nginx:1.21.6

# Update all packages
RUN apt-get update && apt-get -y upgrade

# Use a custom startpage
RUN echo '<html><bod>New Startpage</body></html>' > /usr/share/nginx/html/index.html

Собираем образ еще раз:

$ docker build -t my-custom-nginx .

=> [1/3] FROM docker.io/library/nginx:1.21.6@sha256:e1211ac1…   0.0s
=> CACHED [2/3] RUN apt-get update && apt-get -y upgrade        0.0s
=> [3/3] RUN echo '<html><bod>My Custom Startpage...            0.2s

=> exporting to image                                           0.0s
=> exporting layers                                             0.0s
=> writing image                                                0.0s
=> naming to docker.io/library/my-custom-nginx

Building 2.1s (7/7) FINISHED

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

Кэш ведет себя по-умному. Когда нужно переделать один шаг, заново собираются все последующие шаги. Поэтому стоит размещать часто обновляемые части в конце Dockerfile, чтобы заново использовать предыдущие слои сборки.

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

Как использовать опцию --no-cache с docker build

Причины для отключения кэширования сборки могут быть разными. При помощи опции --no-cache вы можете пересобрать образ из базового образа, не используя кэшированные слои.

$ docker build --no-cache -t my-custom-nginx .

=> CACHED [1/3] FROM docker.io/library/nginx:1.21.6@sha256:...  0.0s
=> [2/3] RUN apt-get update && apt-get -y upgrade               3.5s
=> [3/3] RUN echo '<html><bod>My Custom Startpage...            0.2s

=> exporting to image                                           0.1s
=> exporting layers                                             0.0s
=> writing image                                                0.0s
=> naming to docker.io/library/my-custom-nginx

Building 5.5s (7/7) FINISHED

Новые слои были созданы и использованы. В этот раз docker build запускает обе команды, следуя подходу «все или ничего». Вы можете либо использовать опцию --no-cache для выполнения всех команд, либо кэшировать как можно больше.

Как при помощи аргументов docker увеличить возможности кэша

Есть еще одна опция, позволяющая задать стартовую точку в Dockerfile. Отредактируйте этот файл следующим образом:

FROM nginx:1.21.6

# Update all packages
RUN apt-get update && apt-get -y upgrade

# Custom cache invalidation
ARG CACHEBUST=1

# Use a custom startpage
RUN echo '<html><bod>New Startpage</body></html>' > /usr/share/nginx/html/index.html

Здесь мы добавили аргумент CACHEBUST в том месте Dockerfile, с которого хотели бы начинать принудительную пересборку. Теперь мы можем собирать образ Docker, постоянно передавая разные значения, чтобы все последующие команды запускались заново:

$ docker build -t my-custom-nginx --build-arg CACHEBUST=$(date +%s) .

=> [1/3] FROM docker.io/library/nginx:1.21.6@sha256:e1211ac1...    0.0s
=> CACHED [2/3] RUN apt-get update && apt-get -y upgrade           0.0s
=> [3/3] RUN echo '<html><bod>My Custom Startpage...               0.3s

=> exporting to image                                              0.0s
=> exporting layers                                                0.0s
=> writing image                                                   0.0s
=> naming to docker.io/library/my-custom-nginx

Building 1.0s (7/7) FINISHED

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

Итоги

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

При помощи опции --no-cache можно отключить кэширование или использовать кастомный аргумент docker build для принудительной пересборки с определенного шага.

Понимание кэширования сборок позволяет более эффективно собирать контейнеры Docker.

Перевод статьи «Docker Cache – How to Do a Clean Image Rebuild and Clear Docker’s Cache».

ОСТАВЬТЕ ОТВЕТ

Please enter your comment!
Please enter your name here