сеньорчикОткрыть в Telegram
← вся теориятеория к собесу · Инфраструктура данных

Docker для дата-инженера

Контейнеры: процесс, не виртуалка

Контейнеры - базовая упаковка пайплайнов и сервисов, и путают их с виртуалками. Собес проверяет, понимаешь ли ты, что это изолированный процесс на общем ядре, и почему данные контейнера эфемерны.

Стержень: контейнер - процесс с namespaces и cgroups, а не VM; образ собирается кэшируемыми слоями, и порядок слоёв решает скорость пересборки.

// Формулировки: «чем контейнер отличается от VM?», «зачем слои образа?», «где хранить данные контейнера?».

Процесс и слои

Контейнер - изолированный процесс со своей файловой системой, сетью и лимитами (namespaces плюс cgroups), а не виртуалка: ядро общее с хостом, старт занимает миллисекунды, а не секунды загрузки ОС.

Образ собирается слоями из Dockerfile, и слои кэшируются сверху вниз. Поэтому редко меняющееся (установку зависимостей) ставят раньше, а часто меняющееся (копирование кода) - позже: тогда пересборка после правки кода занимает секунды, а не переустанавливает зависимости заново.

// Обратный порядок - COPY кода до установки зависимостей - промахивается мимо кэша: каждая правка строчки кода запускает многоминутную переустановку.

namespaces / cgroups
изоляция ресурсов / лимиты - основа контейнера
слой
кэшируемый шаг сборки; порядок решает скорость

Эфемерность и один процесс

Данные контейнера эфемерны: рестарт даёт чистую файловую систему. Всё, что должно жить, кладут в volumes, а конфигурацию передают через переменные окружения, а не запекают в образ (принцип 12-factor). Хранить данные БД в ФС (файловая система) контейнера - значит стереть прод при рестарте.

Один контейнер - один процесс или сервис: логи в stdout/stderr, а упавшее перезапускает оркестратор. Супервизор внутри контейнера - антипаттерн.

// Секреты в образ (ENV в Dockerfile, вшитые ключи) попадают в каждый слой навсегда - их оттуда не вычистить. Секреты подают в рантайме, а не встраивают в образ.

volume
переживающее контейнер хранилище данных
12-factor
конфиг через ENV, а не запечён в образ

Теги, multi-stage, лимиты

Образы тегируют версией или коммитом, а не latest: «latest» вчера и сегодня - разные образы, а воспроизводимость деплоя требует закреплённого тега или digest.

Multi-stage build собирает артефакт в тяжёлом образе и копирует его в тонкий рантайм: меньше размер, меньше поверхность атаки; внутри не работают от root.

// Лимиты памяти и CPU обязательны: контейнер без лимитов съедает ноду целиком. И OOMKilled (exit 137) это не «докер глючит», а превышение выданного лимита памяти; лечится лимитом или профилем потребления, а не рестартом.

multi-stage build
сборка в одном образе, рантайм в тонком
OOMKilled
убит за превышение лимита памяти (exit 137)

Как отвечать: «Чем контейнер отличается от VM и зачем слои?»

Виртуалка эмулирует железо и несёт целую гостевую ОС со своим ядром, поэтому она тяжёлая и стартует секундами. Контейнер это просто изолированный процесс на ядре хоста: изоляция достигается namespaces, лимиты - cgroups, отдельного ядра нет. Отсюда старт за миллисекунды, маленький размер и высокая плотность на ноду. Про слои: образ собирается по слоям из Dockerfile, и они кэшируются сверху вниз. Смысл в порядке - редко меняющееся, вроде установки зависимостей, ставят раньше, а часто меняющееся, код, позже. Тогда после правки кода пересобирается только верхний слой, за секунды, а тяжёлая установка зависимостей берётся из кэша. Если перепутать и скопировать код до установки зависимостей, кэш промахивается и каждая правка запускает многоминутную пересборку. Плюс помню, что данные контейнера эфемерны - их в volumes, и всегда ставлю лимиты памяти.

Почему это сильный ответ: контейнер отделён от VM через общее ядро (namespaces/cgroups, старт мс), слои объяснены через кэш и порядок с конкретной ошибкой, добавлена эфемерность и лимиты.

На чём валят

  • Хранить данные БД в ФС контейнера - рестарт стёр прод.
  • COPY кода до установки зависимостей - кэш слоёв мимо, пересборка по 10 минут.
  • FROM latest в проде - невоспроизводимый деплой, «вчера работало».
  • Секреты в образ (ENV в Dockerfile, вшитые ключи) - они в каждом слое навсегда.
  • Контейнер от root с проброшенным docker.sock - фактически root на хосте.

Проверьте себя

Пять вопросов из банка по этой подтеме. Всего их 10, остальные разбираются в тренажёре.

  1. #containers_docker1 / 5
    Как порядок инструкций в Dockerfile влияет на скорость пересборки образа?
    A)Порядок инструкций на скорость пересборки не влияет — Docker собирает образ целиком с нуля
    B)Код нужно копировать в самом начале Dockerfile, чтобы установка зависимостей попадала в кэш
    C)Слои кэшируются; редко меняющееся раньше кода → кэш deps не сбрасывается
    D)Docker кэширует последнюю инструкцию образа, поэтому порядок остальных безразличен
    показать ответ и разбор
    +C)Слои кэшируются; редко меняющееся раньше кода → кэш deps не сбрасывается

    // разбор: Каждая инструкция Dockerfile создаёт слой, и Docker кэширует их: при пересборке слой берётся из кэша, если он и всё до него не изменились. Как только слой меняется, все последующие пересобираются заново. Отсюда правило: сначала копировать файл зависимостей и ставить их (меняются редко), и только потом копировать исходный код (меняется часто). Тогда правка кода не сбрасывает кэш установки зависимостей — пересборка быстрая. Обратный порядок (COPY всего кода до install) переустанавливает зависимости на каждую правку.

  2. #containers_docker2 / 5
    Для чего служит docker-compose?
    A)Docker-compose нужен, чтобы собрать один образ из нескольких разных Dockerfile сразу
    B)Docker-compose распределяет контейнеры по множеству физических узлов кластера для масштаба
    C)Docker-compose заменяет собой Dockerfile и описывает, как собирается сам образ приложения
    D)Описать и поднять многоконтейнерное приложение (например, пайплайн + Postgres + брокер) одной декларацией и командой
    показать ответ и разбор
    +D)Описать и поднять многоконтейнерное приложение (например, пайплайн + Postgres + брокер) одной декларацией и командой

    // разбор: docker-compose описывает в одном YAML набор сервисов-контейнеров, их образы, переменные окружения, тома, сети и зависимости, и поднимает весь стек одной командой (up). Удобно для локальной разработки и тестов: поднять пайплайн вместе с его Postgres, Kafka, MinIO в согласованной сети без ручного запуска каждого контейнера. Для продакшена на кластере обычно переходят на Kubernetes (масштаб, самовосстановление, много узлов), а compose остаётся инструментом локального стека и CI.

  3. #containers_docker3 / 5
    Зачем контейнеру монтируют volume (том)?
    A)Хранить данные вне жизненного цикла контейнера: контейнер эфемерен, а данные в volume переживают его пересоздание
    B)Volume нужен, чтобы ускорить работу контейнера, кэшируя его образ в оперативной памяти хоста
    C)Volume делает контейнер stateful, встраивая всё его состояние прямо внутрь файловой системы контейнера
    D)Данные, записанные в файловую систему контейнера без volume, сохраняются и после его удаления
    показать ответ и разбор
    +A)Хранить данные вне жизненного цикла контейнера: контейнер эфемерен, а данные в volume переживают его пересоздание

    // разбор: Файловая система контейнера эфемерна: удалил/пересоздал контейнер — всё, что писалось внутрь, исчезло. Volume — это хранилище (директория хоста или именованный том), примонтированное в контейнер, живущее независимо от него. Туда кладут данные, которые должны пережить пересоздание: файлы БД, промежуточные результаты, логи. Так контейнер остаётся stateless (легко пересоздать/масштабировать), а состояние вынесено в volume или внешнюю БД. Писать важные данные в саму файловую систему контейнера — частая ошибка: они теряются при рестарте.

  4. #containers_docker4 / 5
    Что даёт multi-stage build в Dockerfile?
    A)Multi-stage build запускает несколько контейнеров приложения параллельно из одного образа
    B)Сборка в одном stage, в финал только артефакт — тонкий образ без build-deps
    C)Он увеличивает финальный образ, включая в него все инструменты сборки ради полноты окружения
    D)Multi-stage build нужен, чтобы собрать образ сразу под несколько разных версий приложения
    показать ответ и разбор
    +B)Сборка в одном stage, в финал только артефакт — тонкий образ без build-deps

    // разбор: Multi-stage build использует несколько FROM: в первом («build») ставят компиляторы, dev-зависимости, собирают артефакт (бинарь, wheel, статику); в финальном образе с минимальной базой копируют через COPY --from только готовый результат, а весь build-инструментарий остаётся в отброшенном промежуточном образе. Итог — маленький, безопасный runtime-образ без лишних зависимостей и мусора. Это стандартный приём уменьшения размера образа и поверхности атаки: не тащить в прод то, что нужно было только для сборки.

  5. #containers_docker5 / 5
    Почему контейнеры проектируют stateless и эфемерными (принцип 12-factor)?
    A)Чтобы контейнер хранил всё своё состояние локально и не зависел ни от каких внешних сервисов
    B)Чтобы каждый контейнер был уникальным и незаменимым, с собственными несохраняемыми данными
    C)Взаимозаменяемость/масштаб/рестарт — состояние во внешних сервисах
    D)Stateless нужен для экономии оперативной памяти на узле, к масштабу отношения нет
    показать ответ и разбор
    +C)Взаимозаменяемость/масштаб/рестарт — состояние во внешних сервисах

    // разбор: Stateless-контейнер не хранит важного состояния локально — оно в БД, объектном хранилище, кэше. Тогда любой экземпляр взаимозаменяем: оркестратор может убить и поднять его на другом узле, запустить десять копий за балансировщиком, обновить без потери данных — контейнеры «как скот, а не питомцы». Это принцип 12-factor app и основа горизонтального масштабирования и самовосстановления в K8s. Если же состояние живёт внутри контейнера, его нельзя безопасно пересоздать или размножить — рестарт теряет данные, копии расходятся.

дальше

Теорию прочитали. Навык ставится повторением

В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.