← Docker
10 мин · просто · Урок 3 из 8

Образы и слои

Образ vs контейнер, слои + copy-on-write, тэги и digest, почему latest — ловушка, что такое registry.

Из чего состоит образ

Со стороны nginx:1.27 выглядит одним файлом. На самом деле это манифест + список слоёв. Манифест — небольшой JSON, описывающий, что лежит внутри. Слои — архивы с дельтами файловой системы.

Когда ты делаешь docker pull nginx:1.27, Docker:

  1. Тянет манифест.
  2. Параллельно качает только те слои, которых у тебя ещё нет.
  3. Складывает их в локальный store, по хешам.

Если у тебя уже лежит nginx:1.26 и большая часть слоёв общая, Docker их переиспользует. Поэтому первое скачивание долгое, а последующие быстрые.

Слои образа

Инструкции RUN, COPY и ADD создают новый слой, то есть архив с тем, что инструкция добавила или изменила. FROM слой не создаёт, а задаёт стартовую стопку слоёв базового образа. Слои read-only, идентифицируются по хешу содержимого и шарятся между образами.

Когда ты запускаешь контейнер, поверх стопки read-only слоёв ложится один writable-слой. Все изменения внутри контейнера пишутся туда. Файловая система контейнера — это слепка снизу вверх через OverlayFS.

writable-слой копия pkg.json COPY . /app RUN npm ci COPY package.json ./pkg.json FROM node:22-alpine writable-слой контейнера пустой, пока процесс ничего не менял read-only слои образа неизменны и общие для всех контейнеров из этого образа правка pkg.json уводит копию наверх
Правка файла не трогает нижний слой: наверх уезжает копия, и видит её только этот контейнер.

Это и есть copy-on-write. Пока файл никто не трогал, он один на все контейнеры из этого образа. Как только кто-то его поменял, копия уезжает наверх, в writable-слой только этого контейнера. Соседние контейнеры всё ещё видят оригинал.

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

Тэги

Тэг — метка на манифесте. nginx:1.27.0, nginx:1.27, nginx:latest - могут указывать на один и тот же образ, а могут на разные. Это просто строки, и владелец репозитория может их двигать как хочет.

Обычные практики:

ТэгЧто значит
1.27.0конкретный патч-релиз, обычно не двигается
1.27минорная серия, двигается на новые патчи
1мажорная серия, двигается на новые миноры
latest«последний стабильный», но кто такой стабильный, решает мейнтейнер
alpine, slimварианты на минимальной базе

latest — ловушка

nginx:latest сегодня указывает на один конкретный образ. Завтра мейнтейнер выпустит новый релиз и сдвинет тэг на него. Твой docker pull подтянет уже другое, хотя строка в Dockerfile не изменилась.

Что ломается:

Простое правило: в проде ставь конкретный тэг (1.27.3) или digest. В dev тоже желательно конкретный, но допустимо 1.27 или 1.

Digest: иммутабельная ссылка

Тэг можно двигать, а digest прибит намертво: это SHA256-хеш самого манифеста. Поменялся манифест → поменялся digest.

docker pull nginx@sha256:abc123…   # заглушка; реальный digest — это полный sha256 из 64 символов

Подсмотреть digest можно так:

docker inspect nginx:1.27 --format '{{index .RepoDigests 0}}'

В проде, где нужна абсолютная воспроизводимость, ссылаются именно по digest. В Kubernetes-манифестах для критичных сервисов делают так же.

Полезные команды по образам

docker pull nginx:1.27         # скачать
docker images                  # список локальных
docker image ls --digests      # с digest'ами
docker history nginx:1.27      # из чего собран образ, какие слои
docker rmi nginx:1.27          # удалить
docker image prune             # удалить безымянные dangling-образы
docker image prune -a          # удалить все, на которые нет контейнеров

docker history показывает каждый слой и какая инструкция его создала - полезно, когда непонятно, откуда в образе раздулся размер.

Registry: где живут образы

Registry — это сервер, который хранит образы. Их много:

Логин:

docker login registry.gitlab.com
docker pull registry.gitlab.com/myorg/myrepo:1.0
docker push registry.gitlab.com/myorg/myrepo:1.0

Полное имя образа — это <registry>/<namespace>/<name>:<tag>. Если <registry> опущен, подставляется docker.io.

Что важно запомнить

Образ — стопка read-only слоёв. Контейнер — writable-слой поверх неё. Copy-on-write: файлы копируются в writable-слой только при изменении.

Тэги двигаются, digest — нет. В проде используй конкретные тэги или digest, а не latest.

Registry — просто HTTP-сервер с образами. Docker Hub подставляется по умолчанию, остальные подключаются через полное имя образа.

В следующем уроке соберём собственный образ через Dockerfile.

Дрилл · вопросы как на собесе

Проверь себя без подсказок

Сформулируй ответ вслух или письменно, потом раскрой и честно отметь: знал или нет.

01

Что такое OverlayFS и copy-on-write? Как хранятся образы?

DOC-017
02

Что такое слои в Docker?

DOC-002
03

Какие инструкции Dockerfile создают слои?

DOC-009
04

Что такое `<none>` образы в выводе `docker images`?

DOC-011
05

В чём риск использования тега `:latest`?

DOC-010

Прошли материал до конца? Отметьте урок пройденным.