Слой RUN пересобирается: сохраняем загрузки пакетов через cache mount

Зависимости вынесены в отдельный слой Dockerfile, и при изменении только кода сборка быстрая. Но стоит добавить один пакет в requirements.txt, как pip скачивает всё заново. Это нормальная граница layer cache: изменился вход RUN, прежний результат шага больше не подходит. Здесь помогает другой вид кэша — каталог загрузок, сохраняемый между исполнениями шага.

Layer cache позволяет вообще не выполнять команду. Cache mount полезен именно тогда, когда команда должна выполниться снова: пакетный менеджер получает возможность повторно использовать ранее загруженные файлы. Эти механизмы дополняют друг друга, поэтому правильный порядок COPY остаётся полезным и после добавления mount.

Дать pip постоянный каталог загрузок

Для BuildKit можно смонтировать cache в стандартный каталог pip. Не добавляйте одновременно --no-cache-dir: он отключает тот кэш пакетного менеджера, который мы хотим переиспользовать.

# syntax=docker/dockerfile:1
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt
COPY . .

Каталог /root/.cache/pip соответствует запуску pip от root в этом build-этапе. Если переключили USER или задали другой PIP_CACHE_DIR, target нужно согласовать. Сам mount не переносится в итоговую файловую систему слоя как обычный COPY. Установленные пакеты остаются результатом pip install, а скачанные материалы служат ускорению следующих сборок.

Cache mount не является надёжным хранилищем обязательного входа. Builder может удалить кэш при очистке, либо новая CI-машина не будет его иметь. Команда установки должна уметь выполниться с пустым каталогом. Версии зависимостей и проверка их происхождения тоже остаются отдельной задачей: наличие старого архива не описывает, какой набор пакетов приложение должно использовать.

Измерить правильный сценарий

Первая сборка прогревает cache. Для второй измените requirements.txt так, чтобы RUN действительно исполнился, например добавьте одну допустимую зависимость в тестовом проекте. В журнале pip посмотрите, какие пакеты берутся из кэша, а какие загружаются. Повторная сборка без изменения входов покажет CACHED на всём RUN и ничего не скажет о пользе mount.

В CI проверьте, сохраняется ли нужный builder между запусками. Локально всё может ускориться, а одноразовый builder в каждом pipeline будет начинать с пустого кэша. Экспорт layer cache и сохранение содержимого cache mounts имеют особенности; не считайте любую настройку cache-to автоматическим переносом всех каталогов пакетного менеджера.

Сравнивайте полный срок сборки и размер обслуживаемого кэша. Если экономия скачиваний мала, а инфраструктура сохранения сложна, простой корректный Dockerfile может быть достаточен. Cache mount оправдан там, где повторное выполнение установки реально происходит часто и загрузки составляют заметную часть времени.

Продолжить практику

Эту настройку проще понимать в составе приложения, у которого есть сеть, данные и понятная процедура обновления. На курсе «Docker и Docker Compose: контейнеризация приложений» вы упакуете HTTP-сервис с PostgreSQL, разберёте конфигурацию, хранение данных и диагностику сбоев. В программе есть локальные лабораторные, работа с registry и версиями образов; итоговый проект включает передачу окружения другому разработчику и проверку восстановления базы.

Посмотреть программу курса

Источник: официальная документация.

Другие задачи по теме: Процессы, сеть, тома и сборка контейнера.

Продолжить на практике

  • Docker и Docker Compose: контейнеризация приложений ↗

    Упакуйте приложение в Docker и запустите его с PostgreSQL через Compose. Образы, сети, тома, диагностика поломок, обновление версий и восстановление данных — с практикой и итоговым проектом.