Новости
Public API для VMware доступен в Serverspace
Serverspace Black Friday
DP
сентября 1, 2026
Обновлено сентября 1, 2026

Docker Rootless Mode Networking: как контейнеры подключаются к интернету

Docker Linux VPS Сети

Rootless-режим Docker решает конкретную задачу: запустить демон и контейнеры без прав root на хосте. Для процессов изоляции это удобно — меньше поверхность атаки, меньше риск, что уязвимость в контейнере превратится в компрометацию всего сервера. Но у этой модели есть обратная сторона: почти вся сетевая подсистема Linux — создание bridge-интерфейсов, veth-пар, правил iptables — исторически требует привилегий суперпользователя. Rootless Docker обходит это ограничение, полностью выстраивая сеть в пользовательском пространстве, и именно поэтому сетевой стек здесь работает иначе, чем в обычном Docker.

В этом материале мы разберём, из каких компонентов состоит сетевая архитектура rootless-режима, как контейнер получает выход в интернет без единого привилегированного вызова и какие ограничения стоит учитывать при переносе продакшн-нагрузок на такую схему. Отдельное внимание уделим настройке — от установки до выбора сетевого драйвера и публикации портов.

Материал рассчитан на системных администраторов, DevOps-инженеров и разработчиков, которые уже знакомы с обычным Docker, но впервые настраивают rootless-режим — например, на выделенном сервере, где нет доступа к root, или в целях повышения изоляции на многопользовательском хосте.

Терминология: основные понятия

Прежде чем переходить к архитектуре, стоит зафиксировать термины — без них дальнейшее описание будет звучать как набор аббревиатур.

Термин Что это
User namespace Механизм ядра Linux, позволяющий процессу считать себя root внутри изолированного пространства идентификаторов, оставаясь непривилегированным пользователем на хосте. На этом механизме держится вся модель rootless.
RootlessKit Инструмент, который оборачивает демон Docker: создаёт user, mount и network namespace, поднимает пользовательский сетевой стек и передаёт управление dockerd. По сути — оркестратор всего rootless-окружения.
slirp4netns Сетевой драйвер по умолчанию. Эмулирует TCP/IP-стек в пользовательском пространстве и подключает его к TAP-интерфейсу внутри network namespace — без прав root и без изменения сетевых настроек хоста.
VPNKit Резервный драйвер, который подключается, если slirp4netns не установлен. Изначально создавался для Docker Desktop на macOS и Windows.
pasta Более новый драйвер (доступен начиная с Docker Engine 25.0), который транслирует пакеты между TAP-устройством и хостом напрямую, без полной эмуляции стека. За счёт этого показывает заметно более высокую пропускную способность, чем slirp4netns.
Port driver Компонент RootlessKit, отвечающий за проброс портов из network namespace на хост — то есть за работу флага -p в docker run.

Как эти компоненты связаны между собой

Проще всего представить это слоями. RootlessKit создаёт изолированное пространство и внутри него разворачивает dockerd — обычный демон, который ничего не знает о том, что работает без root. Сетевой драйвер (slirp4netns, VPNKit или pasta) обеспечивает связь этого пространства с внешним миром. Port driver отдельно решает, как именно порт контейнера станет доступен снаружи. Каждый слой можно настраивать независимо, и в этом — гибкость архитектуры.

Как это устроено: архитектура сетевого стека

Роль RootlessKit как посредника

Обычный Docker создаёт docker0 — bridge-интерфейс на хосте, к которому подключаются veth-пары контейнеров. В rootless-режиме такой трюк недоступен: создание bridge и veth требует CAP_NET_ADMIN. Поэтому RootlessKit запускает dockerd внутри собственного network namespace, а docker0 и остальные Docker-сети существуют только внутри этого namespace. На хосте они не видны — команда ip link show, выполненная от имени обычного пользователя, их не покажет.

Связь между этим изолированным namespace и реальной сетью хоста обеспечивает пара TAP-устройство плюс сетевой драйвер. TAP-интерфейс создаётся внутри namespace, а драйвер читает из него пакеты и переправляет их наружу — уже от имени процесса RootlessKit, у которого достаточно прав для обычных сетевых операций через сокеты хоста.

Пользовательский стек и NAT без iptables

Здесь и проявляется главное отличие. slirp4netns не создаёт правила NAT на хосте — вместо этого драйвер сам эмулирует трансляцию адресов внутри пользовательского процесса. Контейнер получает частный IP (обычно из диапазона 10.0.2.0/24), пакеты уходящего трафика перехватываются TAP-интерфейсом, разворачиваются программным TCP/IP-стеком и отправляются во внешнюю сеть уже как обычные сокеты процесса slirp4netns. Входящий трафик проходит обратный путь. С точки зрения хоста никакой особой сетевой конфигурации не происходит — просто работает ещё один процесс пользователя.

У pasta логика похожая, но реализована легче: вместо полной эмуляции стека драйвер занимается преимущественно трансляцией заголовков пакетов, что снижает накладные расходы на копирование данных между пространствами. На практике это выражается в заметно более высокой пропускной способности — в некоторых бенчмарках pasta приближается к производительности обычного bridge-режима, тогда как slirp4netns заметно отстаёт.

Проброс портов: builtin, slirp4netns, socat, implicit

Публикация порта — отдельная задача, потому что namespace изолирован не только от исходящего, но и от входящего трафика. По умолчанию используется builtin port driver: он открывает слушающий сокет на хосте и перенаправляет соединения в namespace через внутренний RPC-механизм RootlessKit. Это самый быстрый и наименее ресурсоёмкий вариант, но у него есть заметный недостаток — исходный IP-адрес клиента теряется, все входящие соединения внутри контейнера выглядят как пришедшие с локального шлюза.

Если важно сохранить реальный IP клиента, применяют port driver slirp4netns — он пробрасывает порты силами самого сетевого драйвера и поддерживает передачу исходного адреса. Есть и driver socat, который для каждого проброшенного порта запускает отдельный процесс socat — простое, но менее масштабируемое решение, разумное только при небольшом числе портов. Для pasta используется собственный режим — implicit, где проброс портов встроен в саму логику драйвера.

DNS и разрешение имён

Контейнеры в rootless-режиме получают DNS-сервер от слоя эмуляции — как правило, это виртуальный адрес вроде 10.0.2.3, который транслирует запросы в резолвер хоста. С точки зрения приложения внутри контейнера ничего необычного не происходит: nslookup и curl работают привычно. На практике проблемы с DNS почти всегда сводятся к тому, что не поднялся сам сетевой драйвер — ошибки в настройках резолвера встречаются заметно реже.

Производительность и MTU

Плата за пользовательский стек — задержка и нагрузка на CPU: каждый пакет проходит через дополнительный слой копирования данных между namespace и процессом драйвера. Для slirp4netns значение MTU по умолчанию обычно выставляется в 65520, что частично компенсирует потери на мелких пакетах, но для тяжёлых сетевых нагрузок — стриминга, репликации баз данных, высоконагруженных API — разница с обычным Docker всё равно заметна. pasta в этом смысле выигрывает за счёт более лёгкой реализации, но остаётся не таким быстрым, как нативный bridge с правами root.

Практическое применение

Сценарии, где rootless-сеть оправдана

Rootless-режим редко выбирают ради скорости — его выбирают ради изоляции. Несколько типичных сценариев: локальная среда разработки на общем сервере, где у разработчика нет и не должно быть root; CI/CD-раннеры, которые выполняют произвольный код из pull request-ов и не должны иметь возможность выйти за пределы своей песочницы; многопользовательские хосты, где несколько команд запускают контейнеры на одной машине и нужно гарантировать, что compromise одного контейнера не затронет соседей.

Отдельный случай — размещение на VPS, где провайдер не выдаёт полный root-доступ или где сам администратор сознательно ограничивает привилегии сервисных аккаунтов. При развёртывании на VPS от Serverspace rootless Docker позволяет запускать контейнеризованные сервисы под отдельным непривилегированным пользователем, не выдавая ему доступ к остальной системе, — удобно, если на одном сервере соседствуют несколько независимых проектов.

Архитектурный пример: приложение за обратным прокси

Типичная схема выглядит так: rootless-контейнер с приложением слушает непривилегированный порт, например 8080, а перед ним стоит nginx или Caddy — либо тоже в контейнере, либо как системный сервис с правами на привязку к 80 и 443. Такая связка снимает главное ограничение rootless-режима — невозможность напрямую занять порты ниже 1024 — и при этом сохраняет изоляцию самого приложения.

Сравнение сетевых драйверов

Драйвер Производительность Сохранение исходного IP Когда применять
slirp4netns Средняя Да, с port driver slirp4netns Значение по умолчанию, максимальная совместимость
VPNKit Низкая Ограниченно Резервный вариант, когда slirp4netns недоступен
pasta Выше среднего, ближе к нативной Да, через режим implicit Нагруженные сервисы, где важна пропускная способность

Пошаговая настройка

Шаг 1. Подготовка: subuid и subgid

Rootless Docker опирается на диапазоны идентификаторов, выделенные пользователю в /etc/subuid и /etc/subgid. Без них user namespace просто не поднимется.


grep "^$(whoami):" /etc/subuid /etc/subgid
# если записей нет — добавляем диапазон вручную
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $(whoami)

Шаг 2. Установка rootless-режима

Официальный установочный скрипт разворачивает systemd-сервис пользователя и настраивает dockerd под текущим аккаунтом — root на этом шаге не нужен вовсе.


curl -fsSL https://get.docker.com/rootless | sh
dockerd-rootless-setuptool.sh install
docker context use rootless
systemctl --user enable docker
loginctl enable-linger $(whoami)

Последняя команда важна отдельно: она разрешает пользовательским сервисам продолжать работу после выхода из сессии — иначе демон остановится при закрытии SSH-подключения.

Шаг 3. Проверка текущего сетевого режима


docker info | grep -i rootless
ps aux | grep rootlesskit

Вторая команда полезнее, чем кажется: в строке запуска rootlesskit видны фактические флаги --net и --port-driver, а значит — какой драйвер реально используется прямо сейчас.

Шаг 4. Переключение на pasta

По умолчанию используется slirp4netns. Для нагруженных сервисов имеет смысл перейти на pasta — драйвер нужно сначала установить, затем прописать переменные окружения для systemd-юнита.


sudo apt install -y passt
mkdir -p ~/.config/systemd/user/docker.service.d/
cat < ~/.config/systemd/user/docker.service.d/override.conf
[Service]
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_NET=pasta"
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=implicit"
EOF
systemctl --user daemon-reload
systemctl --user restart docker

После перезапуска стоит повторить проверку из шага 3 — в строке процесса rootlesskit должно появиться --net=pasta.

Шаг 5. Публикация привилегированных портов

Если приложению действительно нужен порт ниже 1024 без обратного прокси перед ним, есть два пути. Первый — снизить системную границу непривилегированных портов, второй — выдать capability самому бинарнику rootlesskit.


# вариант 1: снизить порог для всех пользователей
echo "net.ipv4.ip_unprivileged_port_start=0" | sudo tee -a /etc/sysctl.d/99-rootless.conf
sudo sysctl --system

# вариант 2: точечная capability только для rootlesskit
sudo setcap cap_net_bind_service=ep $(which rootlesskit)

Первый вариант проще, но снижает изоляцию для всех непривилегированных процессов на хосте — стоит применять его осознанно, а не по умолчанию.

Шаг 6. Проверка связности


docker run -d --name netcheck -p 8080:80 nginx:alpine
curl -I http://127.0.0.1:8080
docker rm -f netcheck

Если curl вернул HTTP-заголовки — сеть настроена верно, контейнер получает трафик снаружи и, в свою очередь, может достучаться до внешних адресов через тот же слой драйвера.

Шаг 7. Диагностика типичных проблем

Когда что-то не работает, первым делом стоит смотреть логи пользовательского сервиса — там обычно видно, на каком именно шаге упал rootlesskit.


journalctl --user -u docker --no-pager -n 50

Чаще всего причина одна из трёх: не выделены диапазоны subuid/subgid, не установлен пакет slirp4netns или passt, либо на хосте отключена поддержка непривилегированных user namespace на уровне ядра — это стоит проверить отдельно, поскольку некоторые дистрибутивы ограничивают её из соображений безопасности по умолчанию.

Заключение: что важно запомнить

Сетевой стек rootless-режима устроен на других принципах, чем в обычном Docker: вся изоляция строится вокруг пользовательского пространства вместо ядерных примитивов. RootlessKit берёт на себя изоляцию, сетевой драйвер — связь с внешним миром, port driver — публикацию портов, и каждый из этих слоёв можно настраивать под конкретную задачу. slirp4netns остаётся безопасным выбором по умолчанию, pasta — разумным апгрейдом там, где важна пропускная способность, а builtin port driver стоит менять на slirp4netns или implicit, если приложению нужен реальный IP клиента.

Главное ограничение — привилегированные порты и общая просадка производительности относительно root-режима — на практике решается связкой с обратным прокси и выбором более быстрого драйвера. Для сценариев, где изоляция важнее последних процентов пропускной способности — общие серверы, CI-раннеры, мультитенантные окружения на VPS — rootless Docker закрывает задачу, не требуя компромиссов по безопасности.

Оценка:
4 из 5
Аverage rating : 4.7
Оценок: 4
050000 г. Алматы пр. Сейфуллина, д. 502
+7 (771) 944-45-66
ООО «ИТГЛОБАЛКОМ ЛАБС»

Вам также может быть интересно...