ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Docker Rootless: запуск контейнеров без root, user namespace, slirp4netns и cgroup v2

Пошагово настраиваем Docker rootless на Linux: готовим subuid/subgid, ставим и запускаем rootless-демон через systemd --user, разбираем сеть slirp4netns и ограничения cgroup v2. В конце — чеклист и быстрые решения частых ошибок.
Docker Rootless: запуск контейнеров без root, user namespace, slirp4netns и cgroup v2

Rootless-режим в Docker — это запуск и демона, и контейнеров от обычного пользователя без привилегий root. На практике это один из самых простых способов уменьшить потенциальный ущерб: даже если злоумышленник «выбрался» из процесса приложения, он упирается в права непривилегированного пользователя, а не получает полный контроль над хостом.

Но rootless — не «волшебная кнопка». Он опирается на user namespace, меняет модель сети (часто через slirp4netns) и по‑другому взаимодействует с лимитами ресурсов (особенно с cgroup v2). Ниже — практичный маршрут: от требований к системе до продакшен‑схемы и диагностики.

Когда rootless Docker действительно нужен (а когда нет)

Rootless имеет смысл, если вы хотите сократить blast radius и не раздавать sudo там, где он не нужен:

  • несколько проектов/клиентов на одном сервере;
  • доступ разработчикам к сборке/запуску контейнеров без прав администратора;
  • CI/runner на общей машине, где компрометация должна оставаться максимально «локальной»;
  • модель «каждый сервис — отдельный Unix‑пользователь со своим Docker».

Rootless может не подойти, если критичны:

  • максимальная производительность сети и минимальная задержка (usermode‑сеть чаще медленнее);
  • кейсы с низкоуровневыми привилегиями, часть сценариев --privileged, специфические монтирования и драйверы;
  • жёсткое управление ресурсами через cgroup v1 (в rootless проще жить на cgroup v2).

Как это работает: user namespace и «root внутри»

Ключевой механизм rootless Docker — user namespace. Он позволяет процессу быть «root» внутри своего пространства имён, но соответствовать непривилегированному UID на хосте.

Упрощённо: внутри контейнера вы видите UID 0, а снаружи это ваш UID (например, 1000) и/или диапазон «подчинённых» UID (subuid). Поэтому попытки сделать что‑то действительно привилегированное на хосте не сработают: ядро проверяет права хостового пользователя.

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

Что нужно ядру и системе

Перед началом проверьте базу:

  • непривилегированные user namespace разрешены в системе;
  • для пользователя настроены subuid/subgid диапазоны;
  • есть инструменты для rootless‑сети (обычно slirp4netns) и утилиты маппинга UID (uidmap).

Схема маппинга UID/GID через user namespace и subuid/subgid для rootless Docker

Подготовка пользователя: subuid/subgid и лимиты

Rootless Docker требует диапазоны подчинённых UID/GID, чтобы корректно маппировать пользователей внутри контейнеров на хост. Обычно это настраивается через /etc/subuid и /etc/subgid.

Проверьте, что у пользователя есть диапазон:

grep -E '^myuser:' /etc/subuid /etc/subgid

Типичная строка выглядит так:

myuser:100000:65536

Если строк нет, добавьте диапазоны (нужны права root):

usermod --add-subuids 100000-165535 --add-subgids 100000-165535 myuser

После этого перелогиньтесь пользователем (важно для окружения и корректной user‑сессии systemd).

Полезные лимиты для rootless окружения

Rootless‑сценарии часто упираются в число процессов, файловых дескрипторов и ограничения user slice. Быстро проверьте:

ulimit -n
ulimit -u

И состояние user‑сессии:

loginctl show-user myuser
FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Установка и запуск Docker в rootless-режиме

Важная идея: для rootless критично не то, «как поставить docker-ce», а то, как развернуть rootless‑демон под пользователем штатным установщиком.

Под целевым пользователем выполните:

dockerd-rootless-setuptool.sh install

Если скрипт не найден, чаще всего не установлен компонент rootless extras (названия пакетов зависят от дистрибутива). Удобнее всего поставить его из репозитория вашей системы, чтобы получались обновления безопасности.

Запуск rootless-демона через systemd --user

Старт и автозапуск:

systemctl --user enable --now docker

Проверка статуса:

systemctl --user status docker

Чтобы Docker CLI ходил именно в rootless‑демон (особенно в CI или non‑login shell), часто помогает явное указание сокета:

export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock

Проверка:

docker context ls
docker info

Чтобы сервис не умирал после выхода из SSH

Rootless Docker живёт в user systemd. Если сервисы падают после logout, включите linger для пользователя (нужно сделать от root):

loginctl enable-linger myuser

Сеть в rootless Docker: slirp4netns, порт-маппинг и ограничения

В rootless‑режиме Docker не может так же свободно управлять хостовым network namespace и firewall, как rootful‑демон. Поэтому типичный вариант — usermode networking через slirp4netns (часто в связке с rootlesskit).

Чего ожидать:

  • контейнеры получают NAT‑подобную сеть без прав root;
  • порт‑маппинг работает, но реализация отличается от классического bridge;
  • производительность и latency могут быть хуже, чем у rootful bridge;
  • возможны нюансы с доступом к сервисам на хосте и hairpin‑сценариями.

Публикация портов: почему 80/443 «не биндятся»

Rootless Docker не может слушать привилегированные порты (<1024), потому что процесс демона — не root. Практичные варианты:

  1. Использовать высокие порты (например, 8080/8443) и отдавать наружу через системный reverse proxy (nginx/HAProxy), который слушает 80/443.

  2. Разрешить bind на низкие порты для конкретного бинарника через capabilities. Делайте это только если понимаете риски и зачем вам это нужно.

  3. Держать reverse proxy границей: root остаётся только у фронтового веб‑сервера, а приложения живут в rootless‑контейнерах.

Если вы строите типичный веб‑хостинг, связка «reverse proxy + rootless контейнеры» обычно самая предсказуемая: TLS и низкие порты остаются в системном сервисе, а прикладной код работает с минимальными привилегиями. Для внешнего TLS удобно использовать SSL-сертификаты и терминировать HTTPS на прокси.

Как понять, что реально используется slirp4netns

Посмотрите вывод:

docker info | sed -n '1,160p'

Также полезно проверить процессы rootless‑сети:

ps aux | grep -E 'slirp4netns|rootlesskit' | grep -v grep

Если вы одновременно приводите в порядок сетевую политику хоста (nftables/iptables) и поведение Docker, пригодится разбор отличий в статье про Docker и firewall: iptables vs nftables и типовые ловушки.

Диаграмма сети rootless Docker со slirp4netns, пробросом портов и reverse proxy

cgroup v2 в rootless Docker: лимиты CPU/RAM и почему «не применяются»

cgroup v2 — ключевая тема для продакшена. В rootful Docker демон управляет cgroup напрямую. В rootless ограничения ресурсов зависят от того, может ли systemd делегировать контроллеры в user slice, и как настроена система.

Проверьте, что у вас cgroup v2:

stat -fc %T /sys/fs/cgroup

Если видите cgroup2fs, это v2.

Проверка делегирования контроллеров systemd

Проверьте делегирование и подсказки в выводе Docker:

systemctl --user show --property=Delegate
docker info | grep -E 'Cgroup|cgroup'

Симптомы, что лимиты «не работают»:

  • параметры --memory, --cpus принимаются, но контейнер реально не ограничивается;
  • в логах демона есть жалобы на невозможность выставить лимиты;
  • контейнеры оказываются в cgroup без нужных контроллеров.

Для диагностики конкретного контейнера посмотрите PID и cgroup‑путь:

docker inspect --format '{{.Id}} {{.HostConfig.CgroupParent}}' CONTAINER
cat /proc/$(docker inspect --format '{{.State.Pid}}' CONTAINER)/cgroup

Если вы глубже используете systemd‑срезы, лимиты и делегирование, полезно свериться с практикой из материала systemd и cgroups: slices, ограничения и типовые настройки.

Практика: как тестировать лимиты

CPU:

docker run --rm --cpus=0.5 alpine sh -c 'apk add --no-cache stress-ng >/dev/null 2>&1; stress-ng --cpu 1 --timeout 20s'

Память:

docker run --rm --memory=256m --memory-swap=256m alpine sh -c 'apk add --no-cache stress-ng >/dev/null 2>&1; stress-ng --vm 1 --vm-bytes 400m --timeout 20s'

Если контейнер стабильно «уходит» за лимит, значит ограничения не применились, и нужно разбираться с делегированием контроллеров и cgroup v2.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Хранилище и права: где rootless чаще всего «стреляет»

Из-за маппинга UID/GID через user namespace меняются привычные ожидания по правам на файлы. Частые кейсы:

  • bind‑mount директории с хоста: внутри контейнера файлы выглядят «не тем владельцем»;
  • приложение пишет в volume, а на хосте владельцы оказываются в диапазоне subuid;
  • миграция с rootful на rootless ломает права на существующих данных.

Практичный подход: не пытайтесь «подогнать» всё под UID 0. Лучше запускать сервисы от явного пользователя внутри контейнера (например, 1000:1000), и выравнивать права на данных под этот сценарий. Если это тяжело, предпочитайте именованные volumes вместо bind‑mount для чувствительных путей или добавляйте инициализацию прав на старте (entrypoint/init‑скрипт).

Rootless в продакшене: типовая схема деплоя

Для большинства веб‑проектов хорошо работает схема:

  • снаружи — системный reverse proxy на 80/443, он же терминирует TLS;
  • приложения и воркеры — rootless Docker под отдельным пользователем;
  • между ними — публикация портов на 127.0.0.1 (или на отдельный loopback‑адрес);
  • логирование — journald или json-file с ротацией, чтобы не раздувать диск.

Так вы сохраняете минимальные привилегии там, где риск выше (прикладной код), и оставляете root только для сетевой части (низкие порты, TLS, firewall). На практике такая схема отлично ложится на отдельный сервер или VDS, где приложения можно разнести по пользователям и ресурсам.

Частые проблемы и быстрая диагностика

Docker CLI «не видит» rootless-демон

Проверьте сокет и переменную окружения:

echo $DOCKER_HOST
ls -la /run/user/$(id -u)/docker.sock
docker info

Не стартует из-под SSH или падает после logout

Проверьте, что сервис запущен как user‑юнит, и при необходимости включён linger (команда выполняется от root):

systemctl --user status docker
loginctl show-user myuser | sed -n '1,120p'
loginctl enable-linger myuser

Порты не пробрасываются или не доступны снаружи

Уточните, на какой адрес опубликован порт (часто только 127.0.0.1):

docker ps
ss -lntp | grep -E 'docker|rootless|slirp|kit' || true

Для продакшена обычно проще и безопаснее публиковать сервисы на localhost и отдавать наружу через системный reverse proxy.

Лимиты ресурсов «игнорируются»

Сверьте cgroup v2, делегирование и путь cgroup контейнера. Если это виртуальная среда, дополнительно убедитесь, что хостовая система инициализирована на cgroup v2 и не режет контроллеры нестандартными политиками.

Мини-чеклист перед боевым запуском

  • Есть subuid/subgid диапазон у пользователя.
  • Rootless‑демон запускается через systemctl --user и переживает logout (linger включён при необходимости).
  • Сеть понятна: вы знаете, используете ли slirp4netns, и принимаете её ограничения.
  • Определена стратегия портов: reverse proxy на 80/443 или осознанная настройка bind low ports.
  • Проверены лимиты CPU/RAM на cgroup v2 и поведение при OOM.
  • Продуманы права на данные (volumes/bind‑mount) и миграция с rootful.

Итоги

Docker rootless — практичный компромисс между удобством Docker и более строгой моделью привилегий. Он особенно полезен для многопользовательских серверов, CI и ситуаций, когда выдавать sudoslirp4netns, зависимость от корректной настройки user namespace и нюансы применения лимитов на cgroup v2.

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

Поделиться статьей

Вам будет интересно

Nginx proxy_cache for static: S3 origin, revalidation, cache lock OpenAI Статья написана AI (GPT 5)

Nginx proxy_cache for static: S3 origin, revalidation, cache lock

Пошагово настраиваем Nginx как edge‑кэш для статики с origin в S3: proxy_cache_path и cache key, revalidation через ETag/Last-Modi ...
WP-CLI: смена URL в WordPress после миграции, правка двойных слешей, проверка cron и diagnose OpenAI Статья написана AI (GPT 5)

WP-CLI: смена URL в WordPress после миграции, правка двойных слешей, проверка cron и diagnose

После переноса WordPress чаще ломаются не PHP и не веб-сервер, а данные: в базе остаются старые URL, абсолютные ссылки и «кривые» ...
nftables IPv6 firewall: правильный ICMPv6 и Neighbor Discovery без потери сети OpenAI Статья написана AI (GPT 5)

nftables IPv6 firewall: правильный ICMPv6 и Neighbor Discovery без потери сети

IPv6 чаще «падает» не из‑за адресов, а из‑за слишком строгого firewall: блокируют ICMPv6 и ломают Neighbor Discovery, SLAAC и PMTU ...