June 7

Связи и тома: выстраиваем устойчивую инфраструктуру с Docker

Если вы уже понимаете, что Docker позволяет запускать приложение в контейнере, следующий шаг — научиться управлять этими контейнерами гибко: подключать сети, монтировать тома, управлять ресурсами.
В этой статье вы найдёте разбор теста среднего уровня. Мы пройдёмся по каждому вопросу, объясняя, зачем всё это нужно и как это применить в реальных задачах.
Эти навыки особенно ценны для тех, кто участвует в настройке среды разработки, работает в QA, DevOps или на позиции младшего системного администратора.

Вопрос 1

Вы запускаете контейнер с помощью команды docker run -it ubuntu --rm, но команда завершается с ошибкой, и контейнер не создаётся. В чём причина ошибки при запуске?

Обоснование:
В Docker CLI очень важно порядок аргументов:

  • Все флаги (-it, --rm, -v, --name) должны располагаться перед именем образа.
  • После имени образа (ubuntu) может идти только команда, которая выполняется внутри контейнера.
  • В команде docker run -it ubuntu --rm — --rm указан после образа, что вызывает синтаксическую ошибку. Docker CLI интерпретирует это как команду внутри контейнера, а не как флаг Docker.

Корректная команда:

docker run -it --rm ubuntu

Выбранный ответ: Флаг --rm указан после имени образа, поэтому Docker CLI считает его невалидным

Вопрос 2

Почему объединение всех команд установки и удаления временных файлов в рамках одной инструкции RUN решает сразу три проблемы: рост размера образа, медленная сборка и наличие временных файлов внутри образа?

Правильный ответ: Все изменения выполняются в одном слое, временные файлы удаляются до фиксации слоя, что уменьшает размер и ускоряет сборку

Обоснование:

  • Docker создает отдельный слой для каждой инструкции в Dockerfile.
  • Если вы выполняете apt-get update, apt-get install, а затем rm -rf /var/lib/apt/lists/* в разных RUN, то слои с временными файлами всё равно сохраняются в итоговом образе.
  • Объединение этих шагов в один RUN (например, через &&) позволяет:

1.     удалить мусор до фиксации слоя;

2.     уменьшить итоговый размер образа;

3.     ускорить сборку, избегая лишнего кэширования и хранения.

Пример:

RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*

Выбранный ответ: Все изменения выполняются в одном слое, временные файлы удаляются до фиксации слоя, что уменьшает размер и ускоряет сборку

Вопрос 3

Веб-приложение не может подключиться к базе данных сразу после docker-compose up, хотя оба контейнера стартуют. В depends_on — не указан. В логах ошибки подключения. Почему возникает ошибка?

Обоснование:

  • В docker-compose директива depends_on не гарантирует, что сервис действительно "готов" (например, база данных завершила инициализацию).
  • Она лишь определяет порядок запуска контейнеров, но не учитывает задержку готовности (например, инициализация PostgreSQL может занять 2-5 секунд).
  • Поэтому веб-приложение может пытаться подключиться до того, как база начнёт слушать порт, что приводит к ошибке соединения.

Решения:

  • Добавить ожидание готовности в виде:

1.     скрипта ожидания (wait-for-it.sh, dockerize, bash loop);

2.     использовать healthcheck + логику ожидания;

3.     применять retry-логику на уровне кода.

Выбранный ответ: Веб-приложение пытается подключиться к базе данных еще до ее полной готовности

Вопрос 4

Какое сетевое решение в Docker удовлетворит сразу трём требованиям:
A. Масштабируемость без сложной перенастройки сети
B. Минимум изменений в настройках хоста
C. Высокая производительность внутри группы контейнеров

Обоснование:

  • Bridge-сеть:

1.     Локальна на одном хосте;

2.     Позволяет контейнерам общаться по имени;

3.     Идеальна для микросервисов на одном узле, не требует конфигурации хоста;

4.     Изолирует от других контейнеров и внешней сети;

5.     Позволяет масштабировать контейнеры с docker-compose up --scale.

  • Почему не другие:

1.     host — лишает изоляции, портов, масштабирования.

2.     overlay — нужен Swarm/Kubernetes, сложнее, для распределённых систем.

3.     macvlan — сложен в настройке и требует прав на уровне хоста.

4.     none — отключает сеть, не позволяет взаимодействие между контейнерами.

Выбранный ответ: Создать пользовательскую сеть типа bridge и подключить к ней все контейнеры приложения

Вопрос 5

Контейнер web-app перегружает CPU. Нужно:

1.     Узнать, какие процессы создают нагрузку

2.     Получить метрики CPU, памяти, сети

3.     Скопировать файл /var/log/app.log на хост
Условие: без интерактивного входа (docker exec -it запрещён).

Обоснование:

  • docker top <container> — покажет список активных процессов в контейнере (аналог ps aux), без входа в него.
  • docker stats — предоставляет живую статистику по CPU, памяти, сети.
  • docker cp <container>:/path /host/path — позволяет извлечь файлы из контейнера без его остановки.
  • Этот вариант соответствует всем условиям: без exec, без остановки, полный сбор информации.

Выбранный ответ: Использовать docker top для процессов, docker stats для метрик и docker cp для копирования файлов

Вопрос 6

Нужно развернуть локальный Docker Registry для тестового окружения, с выполнением условий:

  • Доступ только из локальной сети
  • Запуск на порту 5000
  • Защита от несанкционированной публикации образов

Обоснование:

  • Публикация порта 5000 (-p 127.0.0.1:5000:5000) обеспечивает доступ только с локального хоста, т.е. исключает внешний доступ.
  • Фаервол (например, iptables, ufw или настройки облачного хоста) дополнительно ограничивает внешние подключения.
  • Это решение позволяет:

1.     Запустить registry на нужном порту

2.     Защитить от внешнего доступа

3.     Контролировать загрузку и выгрузку образов

Остальные варианты либо не ограничивают внешние подключения, либо игнорируют порт 5000, либо предлагают небезопасные (--insecure-registry) или чрезмерно сложные решения (NAT).

Выбранный ответ: Ограничить внешний доступ к Registry через правила фаервола и настроить запуск контейнера с публикацией порта 5000

Вопрос 7

Контейнер backend-api, использующий данные из оперативной памяти, завис. Требуется:

1.     Временно приостановить выполнение для дампа

2.     Затем продолжить работу без потери данных

3.     При критической ошибке — аварийно завершить

Обоснование:

  • docker pause — замораживает все процессы внутри контейнера (через cgroups, без выгрузки из памяти), что идеально для дампа состояния.
  • docker unpause — возобновляет выполнение без потери текущего состояния.
  • docker kill — позволяет немедленно завершить контейнер, в отличие от stop, который отправляет SIGTERM и ждёт.
  • Это — единственная комбинация, которая покрывает все три условия корректно.

Остальные варианты либо не работают без остановки (stop теряет контекст), либо описывают избыточные подходы (wait, restart=always), либо менее гибкие (docker-compose pause лишь обёртка).

Выбранный ответ: Приостановить через docker pause, возобновить через docker unpause, завершить через docker kill

Вопрос 8

Как организовать резервное копирование данных из Docker-контейнера, использующего именованный том?

Обоснование:

  • Это — стандартная практика для резервного копирования содержимого volume, не затрагивая основной контейнер:

1.     Создаётся временный контейнер с примонтированным именованным томом.

2.     Внутри контейнера выполняется tar архивация содержимого тома.

3.     С помощью docker cp архив копируется на хост.

  • Пример команды:

docker run --rm -v my_volume:/data -v $(pwd):/backup busybox sh -c "tar czf /backup/backup.tar.gz -C /data ."

Почему не другие варианты:

  • docker save и load — работают с образами, не с томами.
  • docker volume inspect — не предоставляет прямого доступа к данным.
  • docker exec требует наличие работающего контейнера с подключённым томом, что не всегда надёжно.
  • Удаление контейнера перед бэкапом — рискованно и ненужно.

Выбранный ответ: Создать контейнер с подключённым томом. Выполнить tar-архивацию содержимого тома внутри контейнера. Скопировать архив на хост

Вопрос 9

Как обеспечить регулярное резервное копирование данных из контейнера с MySQL с минимальной нагрузкой на базу и сохранением резервных копий вне контейнера?

Обоснование:

  • Именованный том позволяет разделять хранилище между контейнерами, не дублируя данные.
  • Основной контейнер с MySQL продолжает работать с минимальной нагрузкой.
  • Резервное копирование выполняется через отдельный контейнер, который имеет доступ к тому (например, с помощью --volumes-from или -v mydata:/var/lib/mysql), и может отдать данные во внешний NAS, S3 и т.п.
  • Это безопасный и изолированный способ, не нарушающий работу основной базы.

Почему не другие варианты:

  • --volumes-from при старте базы — устаревший и менее гибкий способ.
  • Копирование через основной контейнер — создаёт дополнительную нагрузку на саму БД.
  • rsync с cron внутри контейнера — лишняя сложность и неуниверсально.
  • bind mount временных директорий — не даёт регулярности и надёжности.

Выбранный ответ: Создать именованный Docker-том, подключить его к контейнеру и выполнять резервное копирование через отдельный контейнер с доступом к тому

Вопрос 10

Какой open-source инструмент подходит для автоматического сбора метрик и имеет удобный и полный интерфейс для анализа?

Обоснование:

Prometheus — это основной open-source инструмент для сбора, хранения и анализа метрик, особенно в Kubernetes и Docker-средах.

Он:

1.     сам опрашивает (pull-модель) источники данных;

2.     поддерживает язык запросов PromQL для аналитики;

3.     имеет встроенный веб-интерфейс, хотя часто его визуализация дополняется Grafana.

Остальные варианты:

1.     Telegraf — агент сбора метрик, но не хранит и не визуализирует их сам.

2.     Logstash — работает с логами, а не метриками.

3.     Grafana — интерфейс визуализации, но не собирает метрики сам.

4.     Elasticsearch — полнотекстовый движок, не специализируется на метриках.

Выбранный ответ: Prometheus

Вопрос 11

Один контейнер потребляет много ресурсов, периодически даёт ошибки записи в БД, но не перезапускается. Другие контейнеры и база данных работают нормально. В чём причина?

Обоснование:

Указанные признаки:

1.     рост потребления CPU и памяти,

2.     логические ошибки и задержки в работе,

3.     отсутствие перезапуска контейнера,

всё это указывает на неправильную работу самого приложения, а именно — утечку памяти.

При утечке:

1.     приложение начинает потреблять больше ресурсов,

2.     страдает производительность,

3.     возникают таймауты, ошибки и отказ при доступе к БД.

Почему не другие:

  • Проблемы сети/версий БД/ограничений ресурсов затрагивали бы всю систему или инициировали бы перезапуск.
  • Docker Daemon и конфликты версий менее вероятны — остальные контейнеры работают стабильно.

Выбранный ответ: Утечка памяти в приложении внутри контейнера приводит к увеличению потребления ресурсов, задержкам и ошибкам записи в базу данных

Вопрос 12

Какое основное преимущество даёт автоматизация тестирования в Docker-контейнере в Jenkins по сравнению с ручной настройкой окружения на каждой машине?

Обоснование:

Docker обеспечивает:

1.     изолированное тестовое окружение, не мешающее основной системе и другим пайплайнам;

2.     предсказуемость результатов тестов, независимо от конфигурации хоста;

3.     воспроизводимость: контейнер можно запустить где угодно с тем же окружением.

В Jenkins это особенно важно — можно запускать любые тесты в стандартной, “чистой” среде без риска повлиять на основную систему Jenkins и другие сборки.

Остальные варианты:

  • уменьшает объём тестов — некорректно;
  • устраняет необходимость проверки кода — неверно;
  • упрощает агрегацию — частная функция, не основное преимущество;
  • подтягивать образы — да, но это не основное отличие от ручной настройки.

Выбранный ответ: Docker позволяет создать изолированное окружение для тестов без влияния на основную систему Jenkins

Заключение

После этого теста вы сможете не просто запускать контейнеры, а строить работающие инфраструктуры: соединять сервисы, работать с томами, следить за метриками.
Эти умения помогут вам стать надёжным членом команды и подготовят к более серьёзным задачам — таким как CI/CD или настройка отказоустойчивости в контейнерных средах.