Почему плохо запускать Docker-контейнер от пользователя root?

«Почему плохо запускать Docker-контейнер от пользователя root?» — вопрос из категории Docker, который задают на 24% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Запуск контейнера от root (USER root по умолчанию) создаёт серьёзные риски безопасности, нарушая принцип минимальных привилегий. Если злоумышленник скомпрометирует приложение внутри контейнера, он получит права root внутри контейнера, что может привести к эскалации привилегий на хост.

Конкретные риски:

  • Уязвимости ядра: Эксплойт может использовать уязвимость в ядре Linux для выхода из контейнера на хост.
  • Монтирование чувствительных директорий хоста: Если том смонтирован без должных ограничений (например, / или /etc), root в контейнере может их модифицировать.
  • Использование --privileged: Даёт контейнеру почти все capabilities ядра, делая его почти эквивалентным процессу на хосте.

Best Practices для смягчения рисков:

  1. Используйте непривилегированного пользователя в Dockerfile.

    FROM alpine:latest
    RUN addgroup -g 1000 appgroup && 
        adduser -u 1000 -G appgroup -s /bin/sh -D appuser
    USER appuser
    COPY --chown=appuser:appgroup app /app
    CMD ["/app/start.sh"]
  2. Запускайте контейнер с явным указанием пользователя.

    docker run --user 1000:1000 my-image
  3. В Kubernetes используйте securityContext.

    securityContext:
      runAsNonRoot: true
      runAsUser: 1000
      runAsGroup: 1000
      allowPrivilegeEscalation: false
      capabilities:
        drop:
          - ALL
  4. Ограничивайте Linux Capabilities. Сбрасывайте все и добавляйте только необходимые.

    docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE my-image
  5. Избегайте --privileged. Вместо этого монтируйте только конкретные устройства (--device) или используйте нужные capabilities.

  6. Используйте пользовательские пространства имён (user namespaces). Это мапит root в контейнере в непривилегированного пользователя на хосте (dockerd --userns-remap=default).