Container Image — это упакованный и готовый к запуску набор файлов, библиотек и конфигураций, необходимых для работы приложения в контейнере. Проще говоря, это «снимок» приложения с его зависимостями, который можно запустить на любой машине, где есть контейнерный движок, например Docker или containerd.
В образ входят:
- базовый слой — операционная система или её минимальная часть (например, Alpine, Ubuntu, Debian);
- зависимости приложения — библиотеки, фреймворки, конфигурационные файлы;
- само приложение и инструкции для его запуска (entrypoint, команды).
💡 Почему это важно
Контейнерные образы обеспечивают единообразие среды: код, протестированный в одном окружении, будет работать так же в любом другом. Это исключает ситуации «у меня на локальной машине всё работало».
Как создаётся
Обычно разработчик пишет Dockerfile, где описывает шаги сборки: какую базу взять, что скопировать, какие команды выполнить. На выходе получается образ, который можно хранить в реестрах (Docker Hub, GitHub Container Registry, Harbor) и скачивать при необходимости.
Пример жизненного цикла Container Image
- Разработчик пишет код и Dockerfile.
- Система CI/CD собирает образ.
- Образ загружается в реестр.
- Kubernetes или другой оркестратор скачивает образ и разворачивает контейнеры.
Для клиента
Использование контейнерных образов упрощает развёртывание, повышает скорость выхода обновлений и улучшает безопасность — можно точно контролировать, из чего состоит рабочая среда.
Пример Dockerfile для простого Python-приложения:
FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "app.py"]
Структура и слои (layers)
Container Image собран из слоёв — неизменяемых наборов файлов. Каждый следующий слой «накладывается» поверх предыдущего, формируя итоговую файловую систему контейнера.
- Базовый слой: минимальная ОС или рантайм (alpine, debian-slim, distroless).
- Слои зависимостей: установленные пакеты, библиотеки, языковые рантаймы.
- Слои приложения: ваш код, статические ассеты, конфиги.
- Метаданные: ,
ENTRYPOINT
,CMD
,ENV
,EXPOSE
— инструкции запуска и описательные поля.LABEL
Образы соответствуют формату OCI Image и хранятся как набор слоёв с контент‑адресацией: каждый слой и манифест имеют криптографический digest (sha256), что делает их идентифицируемыми и кэшируемыми.
Кэширование сборки
Docker/BuildKit кэширует слои: если инструкция в
Dockerfile
Практические приёмы:
- Сначала зависимости, потом код Обновление кода не ломает кэш слоя с зависимостями.
COPY requirements.txt . RUN pip install -r requirements.txt COPY . .
- Игнорируйте лишнее: используйте , чтобы не тащить временные файлы (node_modules, .git, логи).
.dockerignore
- Стабильные версии: фиксируйте версии пакетов, иначе кэш будет часто инвалидироваться.
- BuildKit: включайте — более умное кэширование и параллелизм.
DOCKER_BUILDKIT=1
Размер и производительность
- Используйте тонкие базовые образы (,
alpine
, distroless для продакшна).-slim
- Применяйте multi-stage builds: собирайте в одном этапе, копируйте артефакты в минимальный рантайм.
Пример (Go):
# stage 1: build FROM golang:1.22 AS build WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 go build -o app ./cmd/app # stage 2: runtime FROM gcr.io/distroless/static:nonroot WORKDIR /app COPY --from=build /src/app . USER nonroot:nonroot ENTRYPOINT ["/app/app"]
Результат — минимальный образ без шелла и package‑менеджера, меньше поверхность атаки, быстрее доставка.
Теги, digest’ы и неизменяемость
- Теги (,
:latest
) — удобны, но переопределяемы.:v1.4.2
- Digest () — неизменяемый идентификатор. Для воспроизводимости деплойте по digest’у:
@sha256:…
image: registry.example.com/app@sha256:abc123...
Практика: храните и тег, и digest в манифестах (Kubernetes, Helm), чтобы сочетать читабельность и детерминизм.
Безопасность образов
- Минимизируйте поверхность атаки: distroless/ubi‑micro, убирайте компиляторы и шелл в рантайме.
- Не запускайте от root: , задавайте непривилегированного пользователя.
USER 10001:10001
- Подписывайте образы: Cosign/Notary v2 — верифицируйте в CI/CD и на кластере (Policy/Admission).
- Сканируйте уязвимости: Trivy, Grype, Anchore; включите «break the build» на критических CVE.
- SBOM (Software Bill of Materials): генерируйте CycloneDX/SPDX (Syft, Trivy) и храните рядом с образом.
- Обновляйте базу: регулярно пересобирайте образы с новыми патчами базового слоя.
Регистры и политики
- Хранение: Docker Hub, GHCR, Harbor, ECR/GCR/ACR.
- Репликация между регионами — для снижения latency и отказоустойчивости.
- Политики очистки: автоматическое удаление «висячих» тегов и старых билдов.
- Контроль доступа: RBAC/OIDC, отдельные репозитории на окружение (,
dev
,staging
).prod
Диагностика и дебаг
- Добавляйте минимум инструментов в прод‑образ. Для диагностики — отдельный «debug»-вариант (с шеллом и curl).
- Логи и метрики — вне образа: стандартные потоки и sidecar‑агенты (не прошивайте агенты внутрь).
Шаблон «хорошего» Dockerfile (Node.js)
# build stage FROM node:20-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm ci --ignore-scripts COPY . . RUN npm run build && npm prune --production # runtime stage FROM gcr.io/distroless/nodejs20-debian12:nonroot WORKDIR /app COPY --from=build /app/dist ./dist COPY --from=build /app/node_modules ./node_modules ENV NODE_ENV=production USER nonroot:nonroot EXPOSE 3000 CMD ["dist/server.js"]
Особенности:
- — воспроизводимая установка.
npm ci
- — только runtime‑зависимости.
prune --production
- distroless — минимальный рантайм, — без root.
USER
Для чего это всё клиенту
Контейнерный образ — это стандартная единица поставки ПО. Корректная структура слоёв, воспроизводимая сборка, безопасность и управление тегами уменьшают риски, ускоряют релизы и упрощают аудит. Итог — предсказуемые деплои и контролируемая стоимость (меньше трафика и времени доставки).