Справочник ключевых терминов курса Docker для Junior Data Engineer.
Изолированный процесс на хосте с собственной view файловой системы, сети и pid-namespace. Технически — это набор Linux namespaces (mnt, pid, net, uts, ipc, user) плюс cgroups, ограничивающий что процесс видит и сколько ресурсов потребляет. Не виртуальная машина: ядро общее с хостом, поэтому контейнер запускается за миллисекунды и почти не имеет накладных расходов.
Иммутабельный шаблон файловой системы плюс метаданные (CMD, ENV, USER, ports), из которого создаются контейнеры. Состоит из набора tar-слоёв и JSON-манифеста по спецификации OCI Image. Хранится в registry; адресуется по `repository:tag` или по `repository@sha256:digest`.
Один immutable слой файловой системы образа. Каждая инструкция `RUN`, `COPY`, `ADD` в Dockerfile создаёт новый слой. Слои переиспользуются между образами по content-addressable sha256-хэшу: если слой уже скачан — повторно не качается. Финальный rootfs контейнера — UnionFS-стек этих слоёв сверху read-write слоя.
Open Container Initiative — стандарт от Linux Foundation, фиксирующий формат образов (OCI Image Spec), runtime (OCI Runtime Spec) и distribution (OCI Distribution Spec). Docker, Podman, containerd, CRI-O реализуют OCI, поэтому образ, собранный Docker'ом, запускается на Podman и наоборот.
Серверная часть Docker: daemon `dockerd` + containerd + runc + REST API через unix-сокет `/var/run/docker.sock`. Принимает команды от CLI и оркестрирует жизненный цикл контейнеров. Целевая версия курса — Docker Engine 28 (2025).
Клиент `docker` — то, что пользователь набирает в терминале. Сам по себе ничего не запускает: формирует HTTP-запросы и шлёт их в daemon через сокет. Версия CLI и Engine могут не совпадать (поддерживается API negotiation), но рекомендуется держать их в одной major-версии.
Механизм Linux-ядра, изолирующий ресурсы между группами процессов. Шесть основных типов: mnt (точки монтирования), pid (дерево процессов), net (сетевой стек), uts (hostname), ipc (System V IPC), user (UID/GID mapping). Каждый контейнер получает свой набор namespaces, поэтому `ps` внутри показывает только процессы контейнера, а не хоста.
Control groups — механизм Linux-ядра, ограничивающий и учитывающий потребление ресурсов (CPU, RAM, IO, pids) группой процессов. Через cgroup'ы реализуются флаги `--memory=2g`, `--cpus=1.5`. Современные системы используют cgroup v2 (Ubuntu 22.04+, Debian 12+) — единая иерархия `/sys/fs/cgroup`.
Низкоуровневый компонент, который физически создаёт namespaces/cgroups и запускает процесс. Эталонная реализация — `runc` (Go-обёртка над libcontainer). Над ним — высокоуровневый runtime `containerd`, общающийся с CLI/Engine через gRPC. Docker Engine с версии 1.11 делегирует запуск контейнеров containerd, который в свою очередь зовёт runc; сам Engine отвечает только за API и сборку.
Фоновый процесс `dockerd`, поднимающий API-сервер и управляющий ресурсами. Запускается через systemd-юнит `docker.service`. Без работающего daemon любая команда CLI падает с `Cannot connect to the Docker daemon`. Слушает по умолчанию unix-сокет, опционально — TCP `:2375` (HTTP) или `:2376` (TLS).
Что делать с контейнером при выходе: `no` (дефолт), `on-failure[:N]` (только при ненулевом exit code, опционально N раз), `always` (всегда, даже после `docker stop` при ребуте daemon), `unless-stopped` (always, но не после явного stop). Задаётся `--restart=unless-stopped` или `restart: unless-stopped` в compose.
Код возврата процесса PID 1 контейнера. 0 — успех, 1 — generic error, 125 — ошибка Docker CLI, 126 — команда не исполняемая, 127 — команда не найдена, 130 — SIGINT (Ctrl-C), 137 — SIGKILL (часто OOM), 139 — SIGSEGV. Виден в `docker ps -a` и `docker inspect`.
Образ-фундамент, на основе которого строится свой образ через `FROM`. Типичные варианты: `ubuntu:24.04` (~80 МБ), `debian:13-slim` (~75 МБ), `python:3.13-slim` (~120 МБ), `alpine:3.20` (~7 МБ, musl libc). Выбор base влияет на размер итогового образа, скорость pull, набор утилит для debug и совместимость с C-расширениями Python.
Человеко-читаемый указатель на конкретный manifest образа в репозитории: `python:3.13-slim`, `postgres:16-alpine`, `myapp:latest`. Тег мутабелен — `latest` сегодня и `latest` через неделю могут указывать на разные digests. Для воспроизводимых сборок в проде используют либо semver-теги (`16.4`), либо pinning по digest.
Иммутабельный sha256-хэш манифеста образа: `sha256:9a3b...c4f1`. Адресация по digest гарантирует, что вы получите ровно тот же байт-в-байт образ, что и в прошлый раз. В Dockerfile пишется как `FROM python:3.13-slim@sha256:9a3b...c4f1`. Best practice для production-сборок.
JSON-документ, описывающий образ: список слоёв (их digests и размеры), конфиг (CMD, ENV, USER, exposed ports), архитектура и ОС. Для multi-arch образов существует manifest list (он же manifest index) — корневой документ, ссылающийся на per-arch manifests для linux/amd64, linux/arm64 и т.д.
Логическая группа образов в registry с разными тегами: `docker.io/library/postgres` содержит теги `16`, `16-alpine`, `15.7`, `latest`. Полная ссылка: `<registry>/<namespace>/<repository>:<tag>@<digest>`. Для Docker Hub namespace `library` — для официальных образов, его можно опускать.
Образ, под одним тегом содержащий manifests для нескольких архитектур (linux/amd64, linux/arm64, linux/arm/v7). Docker сам выбирает нужный вариант по архитектуре хоста. Собирается через `docker buildx build --platform linux/amd64,linux/arm64`. Критично для команд, где разработка идёт на Apple Silicon (arm64), а прод — на amd64.
Образы от Google (`gcr.io/distroless/*`), не содержащие shell, пакетного менеджера и базовых утилит. Только runtime (Python, JVM, glibc/musl) и приложение. Размер — десятки МБ, attack surface — минимальный. Минусы: невозможно `docker exec -it ... sh` для debug — нужно `docker run --entrypoint=...` отдельным контейнером с инструментами.
Урезанные варианты официальных образов: `python:3.13-slim`, `debian:13-slim`, `node:22-slim`. Сохраняют glibc и стандартный пакетный менеджер (apt), но выкидывают man-pages, документацию, dev-headers. Хорошее дефолтное место старта для Python-сервисов: совместимы со всеми wheel'ами (в отличие от alpine), но в 3-5 раз меньше полной версии.
Минимальный дистрибутив (~7 МБ) на musl libc и BusyBox. Пакетный менеджер — `apk`. Плюсы: малый размер. Минусы: musl несовместим с pre-built wheels на pypi (cp310-manylinux), поэтому `pip install pandas` собирается из исходников ~10 минут. Для Python — обычно проигрывает `python:3.13-slim` в DE-сценариях.
HTTP-сервис для хранения и раздачи образов по OCI Distribution Spec. Публичные: Docker Hub (`docker.io`), GitHub Container Registry (`ghcr.io`), AWS ECR Public, Quay. Приватные: AWS ECR, Google Artifact Registry, Harbor self-hosted. Команда `docker pull alpine` неявно ходит в `docker.io/library/alpine`.
Публичный registry `docker.io` от Docker Inc. Хранит official images (postgres, python, redis), community-образы. Анонимный pull лимитирован 100 запросами в 6 часов на IP; с авторизацией — 200; платные планы — больше. Частая причина CI-флапов — упереться в rate limit.
GitHub Container Registry — `ghcr.io/owner/repo:tag`. Привязан к GitHub-репозиторию, прав доступа — те же, что и у репо. Без rate-limit. Логин: `echo $GITHUB_TOKEN | docker login ghcr.io -u USER --password-stdin`. Популярный выбор для open-source и команд, уже сидящих в GitHub.
AWS Elastic Container Registry. Приватный реджистри в AWS-аккаунте: `<account-id>.dkr.ecr.<region>.amazonaws.com/repo:tag`. Логин — через временный токен: `aws ecr get-login-password | docker login --username AWS --password-stdin <...>`. Токен живёт 12 часов, поэтому CI-jobs обновляют его перед каждым деплоем.
Любой registry, реализующий OCI Distribution Spec (HTTP API для push/pull manifests и blobs). Docker Hub, GHCR, ECR, Harbor, Quay — все OCI. С 2023 OCI registry также хранят Helm charts, WASM-модули, attestations, SBOMs — превратившись в универсальное хранилище артефактов.
Текстовый файл с инструкциями для сборки образа. Читается построчно сверху вниз; каждая команда даёт промежуточный слой и кэшируется. Имя по умолчанию — `Dockerfile` в корне build context. Альтернативное имя указывается через `docker build -f path/to/Dockerfile.prod`.
Первая инструкция Dockerfile: задаёт base image. Можно `FROM scratch` для абсолютно пустого начала (для статических Go-бинарей). Multi-stage Dockerfile может содержать несколько `FROM` — каждый начинает новый build-этап.
Выполняет команду внутри промежуточного контейнера во время build, результат коммитится в новый слой. Каждый `RUN` — новый слой, поэтому связанные операции цепляют через `&&`: `RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*`. Иначе кэшированный `apt-get update` выдаст устаревший индекс на следующем `RUN apt-get install`.
Копирует файлы из build context (хост) внутрь образа. `COPY src/ /app/src/` — рекурсивно. Поддерживает `--chown=user:group` и `--from=stage` для multi-stage. Не умеет URL и не распаковывает tar — для этого `ADD`. Best practice: всегда `COPY`, не `ADD`, если не нужны его спецфичи.
Расширенный `COPY`: умеет качать URL и автоматически распаковывать tar/gzip/bzip2. Обе фичи — в основном источник багов: URL не кэшируется по содержимому, tar-bomb может развернуться куда не ждёшь. Hadolint советует не использовать `ADD` без явной нужды.
Команда по умолчанию, которая запустится при `docker run` без аргументов. Может быть переопределена. Предпочтительная форма — exec form: `CMD ["python", "app.py"]` (JSON-массив, без shell). Shell form (`CMD python app.py`) запускает процесс под `/bin/sh -c`, и тогда сигналы не доходят до приложения.
Команда, которая запустится ВСЕГДА (в отличие от CMD), а аргументы из `docker run` приклеятся к ней. Если есть и ENTRYPOINT, и CMD: `ENTRYPOINT ["python"]` + `CMD ["app.py"]` означает `python app.py` по умолчанию, но `docker run image other.py` запустит `python other.py`. Так делают entrypoint-скрипты для wait-on-db, миграций.
Устанавливает рабочую директорию для последующих `RUN`, `CMD`, `ENTRYPOINT`, `COPY`, `ADD`. Если папка не существует — создаётся. Лучше, чем `RUN cd /app`: тот `cd` не сохраняется между слоями, так как каждый `RUN` — свой контейнер.
Устанавливает переменные окружения, доступные во время build и в runtime. `ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1`. Влияет на cache: смена ENV инвалидирует все последующие слои. Для build-only значений лучше использовать `ARG`.
Build-time переменная, передаваемая через `docker build --build-arg KEY=value`. Доступна только во время build, в runtime — нет. Объявляется до `FROM` если нужно динамически задать base image. Не использовать для секретов: значения попадают в layer history.
Переключает UID/GID для последующих инструкций и runtime. По умолчанию контейнер бежит от root (UID 0), что является security-проблемой при volume mount хостовых директорий. Best practice: `RUN useradd -m -u 1000 app && USER app`. Hadolint правило DL3002.
Инструкция, задающая команду для проверки живости контейнера. `HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD curl -f http://localhost:8080/health || exit 1`. Состояние видно в `docker ps` (healthy/unhealthy/starting) и используется в Compose как `condition: service_healthy` для `depends_on`.
Несколько `FROM` в одном Dockerfile. Каждый этап имеет свой набор слоёв, но в финальный образ попадает только последний. Между этапами копируется только нужное: `COPY --from=builder /app/dist /app`. Так из 1.2 GB build-образа (с компиляторами, dev-headers) получают 80 МБ runtime-образа.
Файл в корне build context, исключающий пути из отправки в daemon. Синтаксис как у `.gitignore`. Без него `docker build .` тянет `node_modules/`, `.git/`, `dist/`, `__pycache__/`, локальные `.env` — это медленно и опасно (секреты могут попасть в слой через `COPY . .`).
Современный backend для сборки образов (v0.26 в 2025), заменивший legacy builder. Параллельная сборка независимых этапов, `--mount=type=cache` для apt/pip кэша, `--mount=type=secret` для секретов, `--platform` для multi-arch. Включён по умолчанию в Docker Desktop и Engine 23+; CLI обёртка — `docker buildx`.
BuildKit-фича: монтирует именованный кэш-каталог в `RUN`-шаг, переживая между билдами. `RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt` — pip wheel cache не пересоздаётся при каждом build. Сильно ускоряет повторные сборки.
BuildKit: пробрасывает секрет в один `RUN`-шаг без записи в слой. `RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm install`. Секрет передаётся через `docker build --secret id=npmrc,src=$HOME/.npmrc`. Безопасная замена `ARG`-секретов, которые остаются в `docker history`.
Дерево файлов, отправляемое CLI в daemon при `docker build <path>`. Daemon видит только этот контекст, поэтому `COPY ../file .` невозможен. Размер контекста виден в первой строке вывода build: `Sending build context to Docker daemon 142.7MB`. Уменьшается через `.dockerignore`.
YAML-файл, описывающий multi-container приложение: набор services (контейнеров), их networks, volumes, environments. Спецификация Compose v2.39 (2025). Запуск: `docker compose up` (с пробелом — встроенный плагин, заменивший устаревший `docker-compose` Python-script).
Описание контейнера в compose-файле: образ, переменные окружения, порты, volumes, зависимости. Compose создаёт по одному контейнеру на service (или несколько при `--scale`). Имя сервиса — это DNS-имя для других сервисов в той же сети.
Compose-фича: помечает сервисы тегами, чтобы запускать подмножества. `profiles: [test]` — стартует только при `docker compose --profile test up` или `docker compose up service-name` явно. Удобно для опциональных сервисов (kafka-ui, debezium, локальный jaeger).
Дополнительный compose-файл (`docker-compose.override.yml`), который автоматически склеивается с основным при `docker compose up`. Используется для локальных переопределений (mounts, debug-ports), не коммитящихся в git. Явное объединение: `docker compose -f base.yml -f prod.yml up`.
Описывает порядок запуска сервисов. Базовая форма `depends_on: [db]` ждёт только старта контейнера, не готовности сервиса. Расширенная: `depends_on: { db: { condition: service_healthy } }` — ждёт passing HEALTHCHECK. Без второй формы Airflow стартует раньше Postgres и падает с connection refused.
Значения для `depends_on.<svc>.condition`: `service_started` (default, только что запущен), `service_healthy` (HEALTHCHECK passing), `service_completed_successfully` (для one-shot init-контейнеров — миграций, seed-скриптов). Без этого race-condition между app и базой неизбежен.
Загружает переменные окружения в сервис из файла. `env_file: .env.local`. В отличие от `environment:` блока, не попадают в `docker compose config`-вывод и не светятся в logs. Не путать с `.env` файлом — тот раскрывает переменные в самом compose.yml (`image: postgres:${PG_VERSION}`).
Запуск нескольких реплик сервиса: `docker compose up --scale worker=4`. Compose создаст `project-worker-1`, `-2`, `-3`, `-4`. Не работает с явно заданным `container_name` и публикацией портов без range (порт уже занят первым контейнером).
Сетевой драйвер по умолчанию: создаёт виртуальный мост `docker0` на хосте, контейнеры получают IP в подсети 172.17.0.0/16, общаются между собой и с интернетом через NAT. User-defined bridge (созданный через `docker network create`) дополнительно даёт DNS service discovery по имени контейнера.
`--network=host`: контейнер использует сетевой стек хоста напрямую, без NAT и без изоляции. Порты слушаются на хостовых интерфейсах. Быстрее, но небезопасно и не работает на macOS/Windows (там Docker крутится в VM). Применяется для high-performance сетевых приложений на Linux-хосте.
Проброс порта контейнера на хост: `-p 5432:5432` (host:container) или в compose `ports: ["5432:5432"]`. Без этого порт контейнера доступен только из других контейнеров той же сети. `-p 127.0.0.1:5432:5432` биндится только на localhost хоста — обычно безопаснее.
Инструкция Dockerfile, документирующая, какие порты слушает контейнер. НЕ публикует порт на хост, только метаданные для `docker inspect`. Реальная публикация — через `-p` или `ports:`. EXPOSE без publish — частая причина «почему мой Postgres недоступен с хоста».
В user-defined network контейнеры резолвят друг друга по имени сервиса/контейнера. Внутри Compose-проекта `postgres://db:5432` работает потому что `db` — имя service. На default bridge (без user-defined) DNS по имени НЕ работает — только по IP или через legacy `--link`.
Сеть, созданная явно через `docker network create mynet` или автоматически Compose. Изолирована от default bridge, имеет встроенный DNS, поддерживает кастомные subnets. Best practice: для каждого compose-проекта своя сеть; не использовать default bridge.
Сетевой драйвер для multi-host scenarios (Docker Swarm, Kubernetes). Объединяет контейнеры на разных хостах в одну виртуальную L2-сеть через VXLAN-туннели. В single-host setup junior'у не нужен; упомянут для понимания, что в Swarm/k8s ipам контейнеров не место в bridge.
Драйвер, дающий контейнеру MAC-адрес и IP в физической LAN хоста. Контейнер выглядит для роутера как отдельная машина. Применяется редко — для legacy сетевых приложений, требующих L2-broadcast. Не работает на cloud-VM (security groups блокируют).
Монтирование директории хоста внутрь контейнера: `-v /host/path:/container/path` или `--mount type=bind,source=/host,target=/container`. Изменения видны в обе стороны мгновенно. Используется для development (hot-reload кода), не для production (зависимость от пути на хосте, проблемы с UID/GID).
Volume, управляемый Docker: `-v pgdata:/var/lib/postgresql/data` или `volumes: { pgdata: {} }` в compose. Хранится в `/var/lib/docker/volumes/<name>/_data`. Переживает удаление контейнеров. Best practice для stateful-сервисов (Postgres, Redis с persistence, MinIO).
Монтирование RAM как файловой системы внутрь контейнера: `--tmpfs /tmp:size=512m`. Не пишется на диск, исчезает с контейнером. Полезно для temporary файлов, кэшей, security-чувствительных данных. На Linux работает напрямую; на Docker Desktop / OrbStack крутится внутри VM.
Плагин, реализующий backend для named volume. По умолчанию — `local` (директория на хосте). Альтернативы: `nfs`, `cifs`, `aws-efs`, `gcs`. Меняется через `docker volume create --driver nfs ...`. Junior DE чаще использует только `local`.
Storage driver по умолчанию в современных Docker. Использует overlay filesystem ядра Linux: read-only нижние слои (lowerdir) плюс read-write верхний слой (upperdir) контейнера через union mount. Замена устаревших aufs, devicemapper, btrfs.
Стратегия в overlay2: при записи в файл, лежащий в нижнем (read-only) слое, файл сначала копируется в верхний (read-write) слой, и только потом изменяется. Объясняет, почему запись большого файла внутри контейнера может быть медленной — копируется весь файл, даже при изменении одного байта.
Принцип объединения нескольких директорий в одну виртуальную файловую систему. В Docker реализуется через overlay2 на Linux. Позволяет переиспользовать слои между контейнерами: каждый контейнер видит полную rootfs, но физически на диске слои базового образа хранятся в одном экземпляре.
Компонент Docker, отвечающий за работу со слоями образов и rootfs контейнера. Сегодня дефолт — `overlay2` (Linux), `vfs` (как fallback без overlay-поддержки), на macOS/Windows используется VM с overlay2 внутри. Смена driver требует пересоздания всех образов.
Запуск Docker daemon и контейнеров от непривилегированного пользователя через user namespaces. Контейнер думает, что бежит от root (UID 0), но снаружи это UID 100000+. Установка: `dockerd-rootless-setuptool.sh install`. Сильно снижает blast radius CVE в daemon. Минусы: нельзя слушать порты ниже 1024, ограниченная поддержка некоторых storage drivers.
Linux namespace, переставляющий UID/GID внутри контейнера относительно хоста. Контейнерный root (UID 0) маппится в безопасный UID хоста (например, 100000). Активируется через `--userns-remap` или включён по умолчанию в rootless mode.
Гранулярные права root, разделённые на ~40 capabilities (CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, CAP_CHOWN, ...). Docker по умолчанию даёт контейнеру урезанный набор. Управление: `--cap-drop=ALL --cap-add=NET_BIND_SERVICE`. Best practice: дропнуть всё, добавить минимум.
Secure Computing Mode — фильтр syscall'ов на уровне ядра. Docker применяет default seccomp profile, блокирующий ~50 опасных syscall'ов (reboot, kexec_load, mount). Кастомный профиль: `--security-opt seccomp=profile.json`. Отключение (`--security-opt seccomp=unconfined`) — последнее средство.
MAC-система (Mandatory Access Control) на Ubuntu/Debian, ограничивающая, к каким файлам и ресурсам может обращаться процесс. Docker по умолчанию применяет профиль `docker-default`. Альтернатива на RHEL/Fedora — SELinux. Отключение профиля редко нужно и снижает безопасность.
Анализ образа на известные CVE в установленных пакетах. Сканер сверяет manifest слоёв со своей БД уязвимостей (NVD, OSV). Встроен в `docker scout`, Snyk, Trivy. Запуск в CI блокирует деплой образа с HIGH/CRITICAL уязвимостями.
Open-source сканер от Aqua Security: `trivy image myimage:tag`. Находит CVE в OS-пакетах (apt/apk/yum), language-зависимостях (requirements.txt, package-lock.json, go.sum), misconfig в Dockerfile/Compose/Terraform. Быстрый, без external API, легко вкручивается в GitHub Actions.
Линтер для Dockerfile (`hadolint Dockerfile`). Ловит anti-patterns: `apt-get update` без `--no-install-recommends`, `latest` тег у base image, отсутствие `USER`, `pip install` без `--no-cache-dir`. Список правил DL3000-DL4006. Стандартный шаг в CI перед `docker build`.
Библиотека для интеграционных тестов: стартует реальный Postgres/Kafka/Redis в контейнере, отдаёт URL, после теста гасит. Для Python — `testcontainers-python`. Заменяет хрупкие мокающие фикстуры на честные тесты против настоящих баз. Требует доступный docker daemon (Docker Desktop, OrbStack, Rancher).
Флаг `--wait` (с Compose v2.1+): команда блокируется, пока все сервисы с HEALTHCHECK не станут healthy, иначе возвращает ненулевой exit code. Незаменимо в CI: `docker compose up -d --wait && pytest tests/integration`. Без `--wait` тесты стартуют до готовности Postgres.
Web-UI для Kafka (`provectuslabs/kafka-ui`): просмотр topics, partitions, messages, consumer groups, schemas. В compose поднимается одним сервисом рядом с Kafka. Альтернативы: AKHQ, Conduktor, Redpanda Console. Помогает быстро ответить «почему consumer lag растёт?» без `kafka-console-consumer.sh`.
S3-совместимое объектное хранилище (`minio/minio`), запускаемое локально как контейнер. Эмулирует AWS S3 API — те же endpoints `PUT /bucket/key`, presigned URLs, multipart upload. Используется для локального development DE-pipeline'ов, чтобы не платить за S3 и не ждать сеть.