Перейти к содержанию
Innovialabs

Docker-образ и контейнер: слои, теги и жизненный цикл

Основы4 мин

Коротко

Docker-образ — неизменяемый шаблон из read-only слоёв, а контейнер — запущенный экземпляр этого образа с собственным тонким слоем для записи; контейнеры создаются, запускаются, останавливаются и удаляются независимо от образа.

Образ и контейнер в одном предложении

Образ (image) — это шаблон: упакованная файловая система плюс метаданные (команда по умолчанию, переменные окружения, порты). Контейнер — процесс, запущенный из этого шаблона, со своим состоянием. Отношение как у класса и объектов: один образ — много контейнеров.

  • Собранный образ не меняется.
  • Каждый контейнер получает поверх образа слой для записи (writable layer), куда попадают все его изменения файлов.
  • Удаление контейнера удаляет этот слой, но не образ.

Слои: из чего состоит образ

Каждая инструкция Dockerfile, меняющая файловую систему (RUN, COPY, ADD), создаёт новый read-only слой. Слои накладываются друг на друга и переиспользуются между образами.

FROM node:20-alpine        # слои базового образа
WORKDIR /app
COPY package*.json ./      # слой: манифесты зависимостей
RUN npm ci                 # слой: node_modules
COPY . .                   # слой: код приложения
CMD ["node", "server.js"]  # только метаданные, без нового слоя

Почему это важно на практике:

  • Кэш сборки: если изменился только код, Docker пересоберёт лишь последний слой COPY. Поэтому файлы зависимостей копируют раньше остального кода.
  • Экономия места: десять образов FROM одной базы хранят её один раз.
  • Удалённые файлы всё равно весят: удаление файла в следующем слое лишь скрывает его, но не уменьшает предыдущие. Чистите в том же RUN, где файлы появились, или используйте multi-stage сборку.

Посмотреть слои образа:

docker history myapp:1.4
docker image inspect myapp:1.4 --format '{{json .RootFS.Layers}}'

Слой для записи

При запуске контейнера Docker добавляет тонкий writable-слой поверх read-only слоёв образа (copy-on-write). Любой файл, который контейнер меняет, копируется в этот слой.

Что из этого следует:

  • Данные, записанные внутри контейнера, пропадают при его удалении. Для баз данных, загрузок и всего, что должно сохраниться, используйте volumes или bind mounts.
  • Два контейнера из одного образа не видят изменений друг друга.
  • docker diff <container> показывает, что изменилось относительно образа.

Теги и digest

Тег — удобное для человека и подвижное имя: nginx:1.27, myapp:latest. Завтра тот же тег может указывать на другой образ.

Digest — хэш содержимого образа: nginx@sha256:.... Он неизменяем: один и тот же digest всегда означает одни и те же байты.

ТегDigest
Примерmyapp:1.4myapp@sha256:3f1a...
Может изменитьсяДа, можно перезалитьНет
Для чегоЛюдям, названия релизовВоспроизводимые деплои, аудит

Практические правила:

  • Не используйте latest в продакшене — непонятно, что реально запущено.
  • Тегируйте образы версией или SHA коммита из CI.
  • Фиксируйте digest, когда важна воспроизводимость, например в манифестах Kubernetes для критичных сервисов.
docker images --digests
docker inspect --format '{{index .RepoDigests 0}}' myapp:1.4

Жизненный цикл контейнера

Контейнер проходит понятные состояния: created → running → (paused) → exited → removed.

docker create --name web myapp:1.4   # создан, не запущен
docker start web                     # работает
docker stop web                      # SIGTERM, затем SIGKILL по таймауту: exited
docker start web                     # снова работает, тот же writable-слой
docker rm web                        # удалён, writable-слой исчез

docker run — это просто create + start одной командой. Флаг --rm удалит контейнер автоматически после завершения.

Как проверить каждый этап:

docker ps            # запущенные контейнеры
docker ps -a         # все, включая остановленные
docker inspect web   # состояние, mounts, сеть, код выхода
docker logs web      # stdout/stderr основного процесса
docker image ls      # локальные образы

Частые ошибки

  • Относиться к контейнеру как к серверу: ставить пакеты внутри работающего контейнера. При пересоздании изменения исчезнут. Меняйте Dockerfile и пересобирайте.
  • Хранить данные без volumes и терять их после docker rm или нового деплоя.
  • Полагаться на latest и получать на другой машине другой образ.
  • Копить остановленные контейнеры и «висячие» образы. Регулярно чистите через docker container prune и docker image prune, предварительно проверив, что будет удалено.

Частые вопросы

Нет. Остановленный контейнер сохраняет свой writable-слой, и docker start вернёт его с теми же файлами. Данные пропадают только при удалении контейнера, если они не лежат в volume.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.