Контейнеры позволяют вам упаковать ваше приложение таким образом, чтобы оно могло запускаться в разных окружениях. Самая популярная платформа для контейнеризации — 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».
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]