Короткий ответ
Каждая инструкция Dockerfile, изменяющая файловую систему (RUN, COPY, ADD), создаёт новый неизменяемый слой с диффом относительно предыдущего; слои накладываются друг на друга union/overlay-файловой системой.
Как это работает подробнее
сборщик выполняет инструкции Dockerfile последовательно, и после каждой такой инструкции фиксирует результат как отдельный слой с собственным хешем содержимого. Готовый образ — это упорядоченный список ссылок на такие слои плюс метаданные (команда запуска, переменные окружения и т.п.).
Пример кода
Пример конфигурации
$ docker history myapp:1.0
IMAGE CREATED BY SIZE
<missing> RUN apt-get update && apt-get install -y curl 42MB
<missing> COPY . /app 1.2MB
<missing> FROM ubuntu:22.04 77.8MBЧто использовать на практике
- Практика. слои можно посмотреть командой
docker history IMAGE— там видны размер и команда, создавшая каждый слой. Одинаковые слои (по хешу) могут переиспользоваться разными образами на одном хосте, что экономит место на диске и трафик приdocker pull.
Подводные камни
- Риск. думают, что удаление файла в более позднем слое (
RUN rm large_file) уменьшает итоговый размер образа — на самом деле файл физически остаётся в предыдущем слое и продолжает занимать место, просто становится невидимым в финальной файловой системе. Для реального уменьшения размера нужно либо не создавать файл в отдельном слое, либо использовать multi-stage build.