Слои, кэширование и .dockerignore
Почему образ состоит из слоёв, как кэш ускоряет сборку и зачем порядок инструкций так важен.
Слой — результат одной инструкции Dockerfile; образ — это стопка слоёв, наложенных друг на друга.
Образ — это слои
Каждая инструкция (FROM, COPY, RUN) создаёт новый слой — снимок изменений файловой системы. Образ — это слои, сложенные стопкой. Такая структура позволяет переиспользовать слои между образами и кэшировать их при сборке.
Кэш сборки
При сборке Docker для каждой инструкции проверяет: изменилось ли что-то? Если инструкция и её входные данные не поменялись, Docker берёт готовый слой из кэша вместо повторного выполнения. В выводе сборки такие шаги помечены как CACHED — они мгновенные.
Кэш действует «до первого изменения»: как только один слой пересобран, все слои после него тоже пересобираются заново.
Почему порядок инструкций важен
Из правила «после изменённого слоя пересобирается всё» следует ключевой приём. Сравните два варианта:
# Плохо: код копируется ДО установки зависимостей
FROM node:22-alpine
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"]
Здесь любое изменение кода меняет слой COPY . ., и тяжёлый RUN npm install запускается заново при каждой сборке.
# Хорошо: сначала зависимости, потом код
FROM node:22-alpine
WORKDIR /app
COPY package.json package-lock.json .
RUN npm install
COPY . .
CMD ["node", "server.js"]
Теперь, пока package.json не изменился, слой с npm install берётся из кэша, и сборка после правки кода занимает секунды. Правило: то, что меняется реже (зависимости), ставьте выше; то, что меняется часто (код), — ниже.
.dockerignore
Файл .dockerignore исключает файлы из контекста сборки — по аналогии с .gitignore. Это уменьшает контекст, ускоряет сборку и не даёт мусору попасть в образ:
node_modules
.git
*.log
.env
Dockerfile
.dockerignore
Особенно важно исключать node_modules и .git: они большие и не нужны внутри образа (зависимости ставятся через RUN npm install). Заодно .dockerignore защищает от случайного попадания секретов вроде .env в образ.
Итог
- Образ состоит из слоёв; каждая инструкция Dockerfile добавляет слой.
- Неизменённые слои берутся из кэша, но после первого изменения всё ниже пересобирается.
- Зависимости копируют и ставят до кода, а
.dockerignoreубирает лишнее из контекста.