Docker Rootless: установка, настройка и ограничения
Docker Rootless запускает демон Docker и контейнеры от обычного пользователя, поэтому взлом контейнера не даёт root на хосте. Настройка занимает несколько минут: пакет uidmap, подчинённые UID, скрипт dockerd-rootless-setuptool.sh и пользовательская служба systemd. Ниже установка, проверка и обход ограничений.

Содержание
Чем опасен обычный Docker и что меняет rootless
В классической установке демон dockerd работает от root. Чтобы не писать sudo перед каждой командой, пользователя добавляют в группу docker, и с этого момента он фактически получает права root: достаточно запустить контейнер с примонтированным корнем хоста, например docker run -v /:/host, и можно править любые системные файлы. Любая уязвимость в демоне или побег из контейнера тоже дают атакующему root на хосте.
В режиме Rootless и демон, и контейнеры работают от обычного пользователя внутри отдельного пространства имён пользователей. Root внутри контейнера соответствует вашей учётной записи снаружи, а остальные UID контейнера отображаются в диапазон подчинённых идентификаторов из /etc/subuid. Сеть и порты пробрасывает утилита RootlessKit. Итог: взлом контейнера даёт атакующему права вашего пользователя, а не всей системы.
Rootless удобен на рабочей машине разработчика, на общих серверах, где несколько человек запускают свои контейнеры, и в CI. Для продакшена с сетевыми плагинами и тонкой настройкой сети он подходит хуже, ограничения разобраны ниже.
Что должно быть в системе до установки
- утилиты
newuidmapиnewgidmap, их даёт пакетuidmap(в Fedora и Arch они входят вshadow-utilsиshadow); - не меньше 65 536 подчинённых UID и GID для вашего пользователя в
/etc/subuidи/etc/subgid; - systemd и cgroup v2, если нужны ограничения ресурсов. В Ubuntu 26.04, Debian 13, Fedora 44 и Arch cgroup v2 включены по умолчанию.
# Debian и Ubuntu
sudo apt install uidmap
# есть ли у пользователя подчинённые идентификаторы
grep "^$(whoami):" /etc/subuid /etc/subgid
# если пусто, выдать диапазон вручную
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
# какая версия cgroup: cgroup2fs означает v2
stat -fc %T /sys/fs/cgroupОбычно записи в /etc/subuid создаются автоматически при добавлении пользователя через useradd или adduser. Вручную их приходится добавлять для старых учётных записей и пользователей из LDAP. О работе с учётными записями подробнее в статье Пользователи и sudo в Linux.
Установка Docker Rootless по шагам
Шаг 1. Пакеты Docker
Надёжнее всего ставить Docker из официального репозитория docker.com: там есть пакет docker-ce-rootless-extras со скриптом настройки. Если Docker уже установлен из этого репозитория, проверьте, есть ли скрипт:
which dockerd-rootless-setuptool.sh
# Ubuntu и Debian с репозиторием docker.com
sudo apt install docker-ce docker-ce-rootless-extras
# Fedora с репозиторием docker.com
sudo dnf install docker-ce docker-ce-rootless-extrasВ Arch rootless-скрипты ставятся отдельным пакетом из AUR. Без пакетного менеджера Docker предлагает установочный скрипт curl -fsSL https://get.docker.com/rootless | sh, бинарники он кладёт в ~/bin.
Шаг 2. Отключить системный демон
Если раньше работал обычный Docker и он вам больше не нужен, остановите его, иначе скрипт попросит параметр --force:
sudo systemctl disable --now docker.service docker.socket
sudo rm /var/run/docker.sockОбразы и контейнеры системного демона в /var/lib/docker при этом не удаляются, но rootless-демон их не увидит: у него своё хранилище.
Шаг 3. Настройка от обычного пользователя
# без sudo, из обычного сеанса пользователя
dockerd-rootless-setuptool.sh installСкрипт создаёт пользовательскую службу systemd docker.service, запускает её и создаёт контекст Docker с именем rootless. Если чего-то не хватает, он сам выведет, какие пакеты или настройки нужны.
Важно запускать его из полноценного входа в систему, через графический сеанс или SSH. После sudo su - user переменная XDG_RUNTIME_DIR и пользовательский экземпляр systemd обычно не настроены, и установка падает. В таком случае зайдите заново по SSH или используйте machinectl shell user@.
Запуск, автозагрузка и проверка
# управление пользовательским демоном
systemctl --user start docker
systemctl --user enable docker
systemctl --user status docker
# чтобы демон стартовал при загрузке, а не только после входа
sudo loginctl enable-linger $USER
# проверка: должно быть Context: rootless и rootless в Security Options
docker info
docker run --rm hello-worldБез enable-linger пользовательские службы останавливаются, когда вы выходите из последнего сеанса. Для сервера, где контейнеры должны жить постоянно, эта команда обязательна. Подробнее о пользовательских службах и их журналах есть в статье systemctl: управление службами в Linux.
Docker CLI переключается на rootless через контекст, но некоторые программы, например старые плагины IDE или скрипты, смотрят только в переменную окружения. Для них добавьте в ~/.bashrc:
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sockDocker Compose работает с rootless без изменений, команды те же: docker compose up -d. Про сам плагин и формат файлов читайте в материале Docker Compose plugin: современная работа с compose.yaml.
Что работает иначе, чем в обычном Docker
| Возможность | Обычный Docker | Rootless | Что делать |
|---|---|---|---|
| Порты ниже 1024 | Да | Нет по умолчанию | sysctl или setcap для rootlesskit |
| ping из контейнера | Да | Зависит от sysctl | Настроить ping_group_range |
| Лимиты CPU и памяти | Да | Только с cgroup v2 и systemd | Делегировать контроллеры |
| Профили AppArmor для контейнеров | Да | Нет | Полагаться на изоляцию userns |
| Overlay-сети и Swarm | Да | Нет | Обычный Docker или Kubernetes |
| Checkpoint и SCTP-порты | Да | Нет | Обычный Docker |
| Хранилище | Любой драйвер | overlay2, fuse-overlayfs, btrfs, vfs | Не держать данные на NFS |
| Каталог данных | /var/lib/docker | ~/.local/share/docker | Следить за местом в домашнем разделе |
Конфигурация демона лежит в ~/.config/docker/daemon.json, а не в /etc/docker. Не путайте этот каталог с ~/.docker, где хранит настройки клиент.
Порты 80 и 443, ping и лимиты ресурсов
Привилегированные порты
Rootless-демон не может слушать порты ниже 1024. Есть два способа это обойти. Первый разрешает такие порты только RootlessKit, второй разрешает всем непривилегированным программам в системе:
# вариант 1: capability для rootlesskit
sudo setcap cap_net_bind_service=ep $(which rootlesskit)
systemctl --user restart docker
# вариант 2: снизить порог для всех
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee /etc/sysctl.d/90-rootless-ports.conf
sudo sysctl --systemПосле обновления пакета rootlesskit capability из первого варианта может слететь, проверяйте её командой getcap $(which rootlesskit). Самый простой путь вообще ничего не менять: публиковать сервис на 8080 и 8443, а снаружи поставить обратный прокси.
ping и ограничение ресурсов
# разрешить ICMP echo для всех групп
echo "net.ipv4.ping_group_range = 0 2147483647" | sudo tee /etc/sysctl.d/90-ping.conf
sudo sysctl --system
# делегировать пользователю все контроллеры cgroup
sudo mkdir -p /etc/systemd/system/user@.service.d
printf "[Service]\nDelegate=cpu cpuset io memory pids\n" | sudo tee /etc/systemd/system/user@.service.d/delegate.conf
sudo systemctl daemon-reloadПо умолчанию пользователю обычно делегированы только контроллеры memory и pids, поэтому --cpus без этой настройки не сработает. После изменения выйдите из системы и войдите снова.
Права на файлы в томах: самая частая путаница
Внутри контейнера root соответствует вашему UID снаружи, поэтому файлы, созданные root в примонтированном каталоге, на хосте будут принадлежать вам. А вот файлы, которые создаёт непривилегированный пользователь контейнера, например UID 999 у PostgreSQL, на хосте получат UID из подчинённого диапазона вроде 100998. Удалить их обычным rm не получится.
# выполнить команду в пространстве имён rootless-демона
rootlesskit rm -rf ~/projects/db-data
# посмотреть, как UID контейнера отображаются на хост
rootlesskit cat /proc/self/uid_mapДля каталогов с данными приложений используйте именованные тома Docker вместо привязки папок из домашнего каталога. Тома живут в ~/.local/share/docker/volumes, демон сам управляет их правами, и проблема с чужими UID на хосте почти исчезает.
Типичные ошибки, удаление и альтернатива
- Cannot connect to the Docker daemon. Клиент стучится в системный сокет. Проверьте
docker context lsи переменнуюDOCKER_HOST. - newuidmap: write to uid_map failed. Нет записей в
/etc/subuidили пакета uidmap. - Ошибки AppArmor в Ubuntu 24.04 и новее. Ubuntu ограничивает непривилегированные пространства имён пользователей. Пакеты docker.com приносят нужный профиль, а при установке скриптом профиль для rootlesskit придётся добавить вручную по документации Docker.
- Демон не запускается после перезагрузки. Не включены
systemctl --user enable dockerиloginctl enable-linger.
Логи демона смотрите командой journalctl --user -u docker. Если rootless не подошёл, удалите его и верните обычный режим:
dockerd-rootless-setuptool.sh uninstall
rootlesskit rm -rf ~/.local/share/docker
sudo systemctl enable --now docker.service docker.socketЕсли хочется контейнеров без root изначально, посмотрите на Podman: он из коробки работает без демона и без root, а с Quadlet контейнеры оформляются как обычные службы systemd. Подробности в статье Podman Quadlet: контейнеры как службы systemd. Полное описание режима есть в официальной документации Docker.
Частые вопросы
Чем Docker Rootless отличается от добавления пользователя в группу docker?
Группа docker даёт доступ к демону, который работает от root, поэтому её участник фактически получает права root на хосте. В режиме Rootless сам демон работает от обычного пользователя, и взлом контейнера ограничен правами этой учётной записи.
Как запустить контейнер на порту 80 в Docker Rootless?
Выдайте rootlesskit capability командой sudo setcap cap_net_bind_service=ep $(which rootlesskit) и перезапустите демон, либо снизьте порог через sysctl net.ipv4.ip_unprivileged_port_start. Можно также публиковать порт 8080 и поставить перед ним обратный прокси.
Работает ли docker compose в режиме Rootless?
Да. Compose обращается к тому же сокету, что и CLI, поэтому команды docker compose работают без изменений.
Где Docker Rootless хранит образы и контейнеры?
В каталоге ~/.local/share/docker. Настройки демона лежат в ~/.config/docker/daemon.json.
Как удалить Docker Rootless?
Выполните dockerd-rootless-setuptool.sh uninstall, затем удалите данные командой rootlesskit rm -rf ~/.local/share/docker. Системный Docker при необходимости включается снова через systemctl enable --now docker.service docker.socket.
Документация и источники
- Rootless mode, Docker Docs, 2026
- Rootless mode: tips, Docker Docs, 2026
- Rootless mode: troubleshooting, Docker Docs, 2026
Читайте также
Команды проверены на актуальных версиях дистрибутивов на момент обновления. Перед изменением системных настроек сделайте резервную копию.