Пара 16: Готовность, ограничения и конфигурация контейнеров
90 минут · 3 курс, ML.
Содержание и результат
Проверить healthcheck, задать лимиты и не путать порядок запуска с готовностью.
План занятия
0–10: контекст и исходная задача. 10–40: устройство и механизмы. 40–55: демонстрация команд. 55–80: лабораторная работа. 80–90: разбор результата и фиксация исправлений.
Практика выполняется в своей учебной папке и на localhost. Подготовка окружения описана в lab/README.md.
Running, healthy, ready
Процесс существует, проверка проходит и пользовательский путь работает — разные факты.
Running означает, что процесс контейнера не завершился. Healthcheck выполняет отдельную проверку и присваивает состояние healthy/unhealthy. В нашем примере он вызывает /healthz. Не каждый healthcheck проверяет все зависимости: он должен иметь понятный смысл. Readiness — готовность обслуживать запросы, liveness — жизнеспособность процесса; в разных платформах это отдельные механизмы. Docker сам по себе не обязательно перезапускает unhealthy-контейнер: restart policy обычно реагирует на завершение процесса. Поэтому важны мониторинг и реакция, а не только зелёная метка.
Аналогия: свет в кафе горит, кухня готова и заказ выдан — три проверки.
Зависимости Compose
Порядок старта не гарантирует завершение инициализации.
depends_on задаёт зависимость порядка запуска. При condition: service_healthy Compose может дождаться healthcheck зависимости перед запуском потребителя. Это не постоянный контроль её доступности и не магическая защита после сбоя. Приложению всё равно нужны timeout, ограниченные retry и понятное поведение при отказе. В нашем сервисе нет внешней базы, поэтому не добавляем искусственную зависимость ради YAML. На схеме обсуждаем будущий вариант app → база и отмечаем, что старт и готовность могут разойтись во времени.
Аналогия: открыть дверь склада не значит закончить приёмку товаров.
Предел ресурсов и поверхность доступа
Ограничиваем ущерб и наблюдаем результат ограничения.
mem_limit и cpus задают пределы ресурсов учебного app. cap_drop: ALL, no-new-privileges и read_only сокращают ненужные привилегии; /data остаётся разрешённым местом записи, /tmp подключается отдельно. Эти настройки проверяются с реальным приложением: нельзя включить read-only и удивляться отказу записи без тома. Ограничение памяти не создаёт память и может привести к остановке. docker stats показывает наблюдение, а inspect — настроенный предел. Размер Docker Desktop и WSL тоже ограничивает весь запуск. Нам не нужен GPU: учебный проект специально лёгкий.
Аналогия: лабораторная работает в пределах выделенного бюджета, а не занимает всё здание.
Команды и наблюдения
Окружение: Ubuntu / Bash, lab.
docker compose up -d --build
docker compose ps
docker compose exec app python -c "import urllib.request; print(urllib.request.urlopen('http://127.0.0.1:8000/healthz').status)"
docker stats --no-stream
docker compose exec app sh -c "touch /app/test-write"
docker compose exec app sh -c "touch /data/test-write"
Отказ touch /app/test-write — ожидаемый результат политики, не дефект курса. Удалите собственный /data/test-write после проверки.
Ожидаемый результат: Healthcheck становится healthy; запись в /app отказана, в /data разрешена; stats показывает потребление.
Вариант для macOS
Healthcheck и ограничения выполняются внутри Linux-VM Docker Desktop. Показатели контейнера не равны всему потреблению macOS. Проверяйте выделенный Desktop бюджет CPU/RAM и доступность устройства.
docker stats --no-stream
docker compose ps
docker compose exec app id
Практика: Проверки ограничений
- Объясните каждое ограничение базового compose.
- Покажите healthcheck и запрос predict отдельно.
- Проверьте, что код нельзя изменить внутри контейнера, а учебные события можно сохранять.
- Запишите configured limit и наблюдаемое потребление: почему это разные числа?
Результат: Таблица проверок: ожидаемое поведение / наблюдение / вывод.
Проверка: Все ограничения сохраняют рабочий predict; unhealthy не объявляется автоматическим рестартом.
Неисправность для разбора: Read-only root filesystem включён без writable-volume для событий.
Решение и диагностика
Базовый compose уже имеет лимиты, /data volume, tmpfs /tmp и healthcheck стандартной библиотекой Python. Проверьте docker compose ps после времени start_period; docker compose exec app id; docker compose exec app rm /data/test-write. Если healthcheck не проходит, сначала изучите его вывод через docker inspect, затем реальный ответ сервиса. Не снижайте защиту целиком ради одной настройки.
Основные выводы
- Нет, healthcheck и restart policy имеют разные механизмы.
- Ожидание готовности зависимости при запуске, но не гарантию её вечной доступности.
Самостоятельная работа
Составить checklist контейнерного запуска и предложить healthcheck для реального ML-API.