Docker Level Security
30 марта 2026 г.·123 views

🛠 Docker Level Security

Давай еще поговорим про Docker и посмотрим повнимательнее на namespaces, cgroups, chroot, capabilities, seccomp.

Понимание того, что происходит под капотом и как оно работает, помогает выстраивать нормальную модель безопасности, которая позволяет контролировать сборку и разделять процессы, что решает огромные проблемы при экаплуатации.

Поэтому мы разберем то, на что тебе стоит обратить внимание в первую очередь.

• FS: chroot и mount

Внутри контейнера процессы видят корень как результат mount-операций и chroot. Поэтому следует не монтировать чувствительные директории (/var/run/docker.sock, /etc, /var/lib/docker) внутрь рабочих контейнеров. Тем более для stateful сервисов использовать чётко выделенные volume.

# Смотрим mount-namespace контейнера

pid=$(docker inspect -f '{{.State.Pid}}' my-container)

lsns -t mnt -p "$pid"

• Namespaces: изоляция процессов, сети и хостнейма

Напомню, что контейнер — это набор пространств имён: PID, NET, MNT, UTS, USER. Они отвечают за то, какие процессы ты видишь, какие точки монтирования доступны и т.д. Поэтому никогда не используй --pid=host и --network=host в обычных сервисах, потому что это антипаттерн изоляции. Для отладки следует использовать nsenter, а не пробрасывать сервисы напрямую на хост.

# Сравниваем namespace контейнера с хостом

pid=$(docker inspect -f '{{.State.Pid}}' ns-demo)

lsns -p "$pid"

# Войти в namespace контейнера для отладки

nsenter -t "$pid" -n ip addr

• cgroups лимиты

Они контролируют, сколько CPU/ памяти может потреблять группа процессов. Docker создаёт группы под каждый контейнер автоматически, но лимиты нужно задавать ручками. Поэтому для всех боевых сервисов обязательно задавать лимиты --cpus и -m, иначе один runaway процесс кладёт всю ноду. В мониторинге следить за OOMKilled и CPU throttling и при превышении необходимо пересмотреть лимиты.

# Ограничить контейнер по ресурсам

docker run -d --name web \

--cpus="1.0" \

-m 512m --memory-reservation=256m \

nginx:stable

# Смотреть потребление в реальном времени

docker stats web

• Capabilities

Docker по умолчанию урезает capabilities контейнера и выдает только часть привилегий ядра. Поэтому следует не использовать --privileged в проде ни при каких условиях, а также стартовая формула: --cap-drop=ALL и точечный --cap-add только того, без чего сервис реально не работает, как пример, - NET_BIND_SERVICE для портов 80/ 443.

# Посмотреть набор capabilities

docker run --rm -it alpine sh

apk add libcap && capsh --print | grep cap_

# Дропаем все, добавляем только нужное ручками

docker run --rm -it \

--cap-drop=ALL \

--cap-add=NET_BIND_SERVICE \

-p 80:80 nginx:stable

• Seccomp и AppArmor

Даже когда злоумышленник внутри контейнера, - ядро может запретить опасные syscalls или операции с файлами через seccomp/ AppArmor. Docker применяет дефолтный профиль, но для чувствительных сервисов его нужно ужимать под конкретное приложение. Рекомендую включить логирование нарушений профиля, чтобы видеть попытки эскалирований и т.д. до того, как они станут эксплойтом.

# Запустить с кастомным профилем

docker run --rm -it \

--security-opt seccomp=/opt/seccomp/web.json \

alpine sh

# AppArmor

docker run --rm -it \

--security-opt apparmor=docker-default \

alpine sh

• Docker daemon и docker.sock

docker.sock это как root на хосте. Любой, у кого есть доступ к сокету, может запустить привилегированный контейнер и выйти на хост. Поэтому следует:

• не поднимать -H tcp://0.0.0.0:2375 без TLS и mTLS

• не монтировать /var/run/docker.sock в рабочие контейнеры

• для CI-раннеров использовать отдельный нод с отдельными правилами

• доступ к группам docker выдавать только с контролем Segregation-of-Duties

# Кто имеет доступ к сокету

ls -l /var/run/docker.sock

getent group docker

# Минимальный systemd-конфиг: только unix-сокет

ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock

#appsec #devsecops #reco #specialty #containersecurity

#appsec#devsecops#reco#specialty#containersecurity
Открыть в Telegram