Образ контейнера и OCI
| Организация | Open Container Initiative (Linux Foundation) |
|---|---|
| Основана | июнь 2015 |
| Спецификации | Image Spec, Runtime Spec, Distribution Spec |
| Версии 1.0 | июль 2017 (Image и Runtime), май 2021 (Distribution) |
| Эталонная среда | runc |
| Адресация | SHA-256 дайджесты (content-addressable) |
| Инструменты | Docker, Podman, Buildah, containerd, skopeo, crane |
Образ контейнера (англ. container image) — неизменяемый пакет, содержащий всё, что нужно для запуска приложения: файловую систему с программой и её зависимостями плюс метаданные о том, как её запускать (команда, переменные окружения, рабочий каталог, пользователь). Из одного образа можно запустить сколько угодно контейнеров. OCI (Open Container Initiative) — организация при Linux Foundation, которая стандартизировала формат образов, способ их запуска и протокол раздачи, чтобы образ, собранный одним инструментом, работал в любом другом.[4]
История
Формат образов в массы принёс Docker (2013). Когда вокруг контейнеров выросла экосистема, конкуренты (CoreOS со своим форматом appc) и сама Docker договорились о едином стандарте: в июне 2015 года была основана OCI. Docker передал в неё код своей низкоуровневой среды выполнения — так появился runc — и формат образа Docker v2, ставший основой спецификации. Версии 1.0 Image Spec и Runtime Spec вышли в 2017 году, Distribution Spec — в 2021-м, а версия 1.1 (2024) добавила хранение произвольных артефактов (подписей, SBOM) рядом с образами.[6]
Три спецификации
| Спецификация | Что описывает |
|---|---|
| Image Spec[1] | формат образа: манифест, конфигурация, слои, индекс для нескольких платформ |
| Runtime Spec[2] | как запустить «распакованный» контейнер (bundle): каталог rootfs + config.json |
| Distribution Spec[3] | HTTP API реестра для загрузки и выгрузки образов (/v2/...) |
Благодаря этому разделению Docker, Podman, Buildah, containerd и CRI-O взаимозаменяемы: собрали образ одним — запустили другим, а Kubernetes работает с любой совместимой средой.
Устройство образа
Образ OCI состоит из объектов, каждый из которых адресуется по содержимому — SHA-256 дайджесту (например, sha256:9b2a…):
- Слои (layers) — tar-архивы (обычно сжатые gzip или zstd) с изменениями файловой системы. Каждая инструкция
RUN,COPY,ADDв Dockerfile порождает новый слой. Удаление файла в верхнем слое записывается специальной меткой whiteout. - Конфигурация — JSON с командой запуска (
Entrypoint,Cmd), переменными, портами, архитектурой и историей сборки. - Манифест — JSON со ссылками на конфигурацию и слои по дайджестам.
- Индекс (image index, «мультиархитектурный образ») — список манифестов для разных платформ:
linux/amd64,linux/arm64и т. д. Клиент сам выбирает подходящий.
При запуске контейнера слои накладываются друг на друга с помощью объединяющей файловой системы (обычно overlayfs), а сверху добавляется тонкий записываемый слой контейнера.[5] Слои общие: если десять образов основаны на одном python:3.12-slim, базовые слои хранятся и скачиваются один раз.
Теги и дайджесты
Полное имя образа: реестр/репозиторий:тег@дайджест, например docker.io/library/nginx:1.27.
- Тег — изменяемый ярлык:
latestили1.27сегодня и через месяц могут указывать на разные образы. - Дайджест — неизменяемый:
nginx@sha256:…всегда даёт ровно тот же образ. В продакшене и CI образы рекомендуют фиксировать по дайджесту.
Тег latest не означает «самый новый» — это просто тег по умолчанию, который никто не обязан обновлять.
Работа с образами
docker build -t registry.example.com/app:1.4.0 . # собрать
docker image inspect app:1.4.0 # конфигурация и слои
docker history app:1.4.0 # какой инструкцией создан каждый слой
docker push registry.example.com/app:1.4.0 # загрузить в реестр
docker buildx build --platform linux/amd64,linux/arm64 -t app:1.4.0 --push .
skopeo inspect docker://docker.io/library/alpine:3.20 # посмотреть образ без скачивания
Образы хранятся в реестрах (Container registry): Docker Hub, GitHub Container Registry, GitLab Registry, Harbor, облачные реестры.
Хорошие практики
- Минимальная база:
alpine,-slim, distroless — меньше размер и меньше уязвимостей. - Многоэтапная сборка (multi-stage): компилятор и инструменты сборки остаются в промежуточном этапе и не попадают в итоговый образ.
- Порядок инструкций от редко меняющихся к часто меняющимся — так кеш слоёв работает лучше.
- Не класть секреты в слои: удалённый в следующем слое файл всё равно остаётся в истории образа.
- Подписывать образы (cosign, Notation) и сканировать на уязвимости (Trivy, Grype).