Docker LinuxWindows (Docker Desktop)macOS (Docker Desktop)

Docker build не использует кэш после небольшой правки — как найти причину

  • Обновлено
  • Чтение ≈ 5 минут

Краткий ответ

Кэш Docker строится послойно: изменение раннего COPY инвалидирует этот слой и всё, что ниже него. Задача — не отключить кэш, а поместить редко изменяющиеся зависимости до часто изменяемого исходного кода.

В этой статье
  1. Что означает ошибка и при каких условиях возникает
  2. Как различить причины
  3. Пошаговая диагностика и исправление
  4. Минимальный пример для отдельного тестового проекта
  5. Как проверить результат и что делать, если проблема осталась

#Что означает ошибка и при каких условиях возникает

При каждой сборке Docker заново выполняет долгие шаги, хотя изменился один файл? Сравните журнал сборки, порядок COPY и RUN, файлы контекста и настройки BuildKit. Кэш Docker строится послойно: изменение раннего COPY инвалидирует этот слой и всё, что ниже него. Задача — не отключить кэш, а поместить редко изменяющиеся зависимости до часто изменяемого исходного кода.

#Как различить причины

Возможная причинаКак узнатьЧто делать
COPY . . расположен до установки зависимостейЛюбое изменение исходного файла изменяет ранний COPY, из-за чего последующий RUN npm ci выполняется заново.В сборке после COPY . . повторяется долгий RUN npm ci.Сначала копировать package*.json, затем устанавливать зависимости, потом копировать исходники.
В контекст попадают изменчивые файлыВ .dockerignore не исключены каталоги журналов, локальные зависимости и временные файлы.Контекст сборки содержит много файлов, а COPY неожиданно перестраивается после мелких локальных действий.Добавить безопасные исключения к .dockerignore, не скрывая нужные для сборки файлы.
Запускается сборка без кэша или с другим строителемВ командах есть --no-cache, изменился buildx builder, платформа или кэш не сохранён между CI-запусками.Строки CACHED не появляются даже при повторе без изменений.Сравнить реальные команды и доступное хранилище кэша.
Меняются входные значения ранних слоёвИзменён Dockerfile, build ARG или файл зависимостей; при копировании ключевых файлов это нормально.Повторно выполняется первый слой, для которого изменилась инструкция или её вход.Зафиксировать входные значения и отделить изменяемые файлы от стабильно используемых.

#Пошаговая диагностика и исправление

  1. Найдите Dockerfile и команду сборкиВ VS Code откройте проект через «Файл» → «Открыть папку»; найдите Dockerfile рядом с исходниками либо путь в compose.yaml → services → build → dockerfile. Откройте встроенный терминал через «Терминал» → «Создать терминал» или обычный терминал ОС и перейдите в каталог сборки. Выполните docker version и docker buildx version: без работающего движка и builder анализ кэша будет неверным.
  2. Повторите одинаковую сборку с подробным журналомВ учебном каталоге с Dockerfile выполните docker build --progress=plain -t local-cache-demo:dev . дважды, ничего не меняя между запусками. Точка означает текущий контекст, -t — локальное имя образа. Во второй сборке при сохранённом кэше многие шаги будут отмечены CACHED; если нет, запишите первый шаг без CACHED. Не используйте --no-cache для этой диагностики и не подставляйте образ корпоративного производства без разрешения.
  3. Сравните порядок COPY и RUNПрочитайте Dockerfile сверху вниз. Если перед RUN npm ci написано COPY . ., любое изменение файла проекта способно повторно запустить установку зависимостей. В Node-проекте с package-lock.json перенесите копирование package.json и package-lock.json перед npm ci, а COPY . . — после установки. Это применимо только к проекту с корректным lock-файлом; для Python/Java/Go принцип тот же, но имена файлов зависимостей другие.
  4. Уберите из контекста ненужные и секретные файлыВ корне контекста создайте или откройте файл .dockerignore. Для Node-примера можно добавить node_modules, .git, *.log и .env, если эти файлы не нужны для сборки; не исключайте исходники, package-lock.json или файлы, которые копирует Dockerfile. Это уменьшит контекст, а исключение .env снизит риск попадания секретов в образ. После правки проверьте, что Dockerfile всё ещё успешно собирается.
  5. Проверьте параметры сборки и платформуПосмотрите фактическую команду из терминала или журнала сборки проекта. Уберите случайный --no-cache, убедитесь, что вы используете тот же buildx builder и ту же платформу. Выполните docker buildx ls, чтобы увидеть активный builder (он помечен звёздочкой). При сборке в новой среде CI локального кэша может не быть вовсе; для общего кэша нужна отдельная настройка cache-to/cache-from, которую согласуют с владельцем инфраструктуры.
  6. Проверяйте изменение именно одного исходного файлаВ учебной копии проекта поправьте только комментарий в src либо main.js и запустите ту же команду сборки. В правильно организованном Node-примере шаг RUN npm ci остаётся CACHED, а поздний COPY . . и следующие после него шаги могут выполняться заново. Если повторный npm ci снова не кэшируется, сравните, не менялся ли package-lock.json, ARG, образ-основа или builder.
  7. Убедитесь, что ускорение не скрывает нужное обновлениеПосле сборки запустите тесты приложения в том порядке, который принят в вашем проекте, и убедитесь, что исходное изменение действительно находится в новом образе. При обновлении пакетов изменение lock-файла обязано заново выполнить установку; это корректное поведение. Не очищайте кэш ради исправления неоправданных перестроений — сначала ищите изменившийся ранний слой.
  8. При отсутствии кэша в CI изучите окружение сборщикаЕсли локально повторная сборка использует CACHED, но каждая сборка в CI идёт с нуля, сравните, сохраняется ли каталог/память сборщика между задачами и есть ли настроенный внешний кэш BuildKit. Не добавляйте публикацию кэша в общий реестр с секретами без рассмотрения угроз. Запишите вывод docker buildx ls и первую некэшируемую инструкцию для ответственного за CI.
  9. Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
    Выберите подходящий вариант — это не команды для последовательного выполнения
    Вариант 1Только просмотр клиента, компонента сборки и списка builder.
    Linux · Терминал (Bash)Команда
    Только просмотр клиента, компонента сборки и списка builder. Если buildx отсутствует, уточните установленную версию/компоненты Docker.
    docker version
    docker buildx version
    docker buildx ls
    Вариант 2Запускать из отдельного тестового каталога, где есть Dockerfile.
    Linux · Терминал (Bash)С осторожностью
    Запускать из отдельного тестового каталога, где есть Dockerfile. --progress=plain показывает подробный журнал и отметки CACHED; -t задаёт локальный тег. Сборка создаёт новый образ и может загружать зависимости.
    docker build --progress=plain -t local-cache-demo:dev .

    Команда может изменить состояние системы или её настройки. Проверьте параметры и последствия перед запуском.

#Минимальный пример для отдельного тестового проекта

Текст
Исправленный Dockerfile для Node-проекта с существующими package.json, package-lock.json и server.js. При изменении server.js слой npm ci обычно остаётся в кэше.
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
CMD ["node", "server.js"]
Текст
Файл .dockerignore в корне контекста сборки. Исключения подходят для приведённого Node-примера; не копируйте их без сверки с потребностями своего проекта.
node_modules
.git
*.log
.env

#Как проверить результат и что делать, если проблема осталась

Ожидаемый результат: при повторной сборке без изменений большинство инструкций CACHED, а после изменения только исходников слои установки зависимостей остаются CACHED. Если нет, начните с первого некэшируемого слоя; одинаковый тег образа сам по себе не гарантирует неизменность базы или платформы.

Так эту ошибку тоже называют

Источники и обновления

Последнее обновление статьи: 2 ноября 2026. Версии программ и интерфейсы меняются — если шаги не совпадают с вашей версией, сверяйтесь с документацией производителя.