DevOps & Infrastructure

Docker в production:
10 ошибок,
которые убивают uptime

Инфраструктура, которая не ломается. Разбираем типичные подводные камни, которые приводят к падению сервисов и сложным расследованиям инцидентов.

Docker контейнер в production окружении

Деплой приложений в Docker — это стандарт индустрии, но это не значит, что он прост. Многие разработчики интегрируют Docker в CI/CD, но забывают о специфике production-окружения. Ошибки на этапе сборки или конфигурации редко видны сразу, но проявляются в самые неподходящие моменты.

Ошибка 1: Запуск контейнеров от root

Самая очевидная, но часто игнорируемая ошибка. Запуск контейнера с UID 0 (root) открывает путь к катастрофе. Если в вашем образе будет найдена уязвимость (например, CVE-2021-3124 в Glibc), злоумышленник получит неограниченные права на хост-машине.

Решение: Всегда создавайте отдельного пользователя внутри контейнера и переключайтесь на него. Это стандарт безопасности, прописанный в лучших практиках Docker.

# Dockerfile
FROM python:3.11-slim
WORKDIR /app
RUN useradd -m appuser
USER appuser
COPY . .
CMD ["python", "app.py"]

Ошибка 2: Образы без multi-stage build

Использование одного слоя для сборки и запуска приводит к огромному размеру образов. Больший образ = больше поверхности атаки, больше времени на скачивание и загрузку (pull/push) в реестр.

Решение: Используйте multi-stage build. Сборщик (builder) может удалять промежуточные артефакты, а в итоговом образе останется только исполняемый бинарник и минимальные зависимости.

# Dockerfile (Multi-stage)
FROM golang:1.21 AS builder
WORKDIR /src
COPY . .
RUN go build -o myapp

FROM alpine:latest
COPY --from=builder /src/myapp /usr/local/bin/myapp
CMD ["myapp"]

Ошибка 3: Нет health check — нет понимания состояния

Docker считает контейнер «здоровым», только если он запущен. Приложение может падать, потреблять 100% CPU или зависать в цикле обработки, но контейнер продолжит гореть зелёным в `docker ps`.

Решение: Определите HEALTHCHECK в Dockerfile. Это команда, которая выполняется внутри контейнера с заданной периодичностью. Если она возвращает ошибку, Docker перестаёт отвечать на запросы и перезапускает контейнер (если настроено).

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1

Ошибки с логированием и ротацией

По умолчанию Docker использует драйвер json-file. Это удобный формат, но он имеет суровое ограничение: размер файла ограничен конфигурацией демона (по умолчанию 10МБ). Без ротации контейнер заполнит диск, ОС заблокирует запись, и приложение упадёт с ошибкой No space left on device.

Решение: Используйте внешние драйверы, такие как syslog, journald или loki. Или, если используете json-file, обязательно монтируйте том с логами и настраивайте ротацию через logrotate или параметры Docker (log-opt max-size).

Правильная стратегия restart policy

Часто можно встретить restart: always. Это работает, но заставляет Docker бесконечно перезапускать контейнер, даже если приложение не может запуститься из-за ошибок конфигурации (например, отсутствует переменная окружения).

Решение: Используйте restart: unless-stopped. Это наиболее безопасная стратегия для production. Контейнер перезапустится, если он упал, но не будет пытаться стартовать, если он уже остановлен вручную.

Контроль версий

Никогда не используйте тег latest в production-конфигурациях. Это нарушает принцип воспроизводимости. Всегда указывайте фикс SHA или семантический номер версии (v1.2.3).

Secrets Management

Не храните пароли и API ключи в переменных окружения или в Dockerfile. Используйте docker secrets или внешние системы типа HashiCorp Vault.


Чеклист для production-деплоя

Перед запуском убедитесь, что вы проверили всё следующее:

  • Собран образ с использованием multi-stage build.
  • В Dockerfile прописан USER для непривилегированного пользователя.
  • Добавлен HEALTHCHECK для критических сервисов.
  • Настроен логгер (syslog/loki) и ротация файлов.
  • Используется restart: unless-stopped.
  • Секреты извлечены из переменных окружения и не закэшированы в образе.

Нужна инфраструктура, которая работает?

GlyphKit обеспечивает высокую доступность и предсказуемую производительность для ваших Docker-контейнеров. Выделенные ресурсы, NVMe и быстрая сеть.