Миграция с Docker на rootless Podman: когда оправдано и как сделать
Привет! Я, Семёнов Евгений Сергеевич, возглавляю ITFresh. Только представьте: на восьми наших серверах Dell Xeon Platinum 8280, что надёжно стоят в московском дата-центре МТС, сейчас одновременно работают сотни клиентских контейнеров. Последние два года мы активно переводим часть продакшн-нагрузки. С Docker переходим на rootless Podman. Разумеется, это не повсеместно! Мы делаем это только там, где такой шаг даёт реальные преимущества: это про безопасность, и, конечно, про бесшовную интеграцию с systemd. Хотите узнать, как всё прошло? Я поделюсь нашим опытом этой миграции: расскажу, что удалось сделать гладко, а где, честно признаюсь, мы, к сожалению, споткнулись.
Зачем вообще менять Docker
У Docker есть одна архитектурная проблема: демон работает от root. Любой пользователь, состоящий в группе docker, фактически получает root-доступ к хосту — может через -v /:/mnt смонтировать файловую систему и писать куда угодно. Для мультитенантных серверов это бесполезный уровень изоляции.
Podman rootless работает иначе:
- Главное отличие: нет демона. Контейнеры здесь — это просто обычные процессы пользователя, которыми управляют напрямую через fork/exec.
- Каждый пользователь имеет свой маппинг UID через
/etc/subuidи user namespaces. - Интеграция с systemd из коробки (
systemctl --user, quadlet). - OCI-совместимость — это очень удобно. Используйте те же самые образы, к которым вы привыкли в Docker Hub. Никаких проблем с совместимостью.
Когда НЕ надо мигрировать
Вот что я сразу хочу сказать всем нашим клиентам: нет никакого смысла затевать миграцию просто ради самой миграции. Зачем что-то менять, если и так всё отлично работает? Смело оставайтесь на Docker, если:
- Если у вас всего один сервер, вы — root-админ, и всё и так прекрасно работает, зачем что-то трогать?
- Если вы используете Docker Swarm для оркестрации, сразу скажу: Podman его не умеет. Тут выбор очевиден.
- Требуются серьёзные сетевые привилегии для приложения? Например, VPN или raw-сокеты? Rootless Podman здесь сильно ограничен, имейте в виду.
- Если ваш CI/CD-процесс глубоко завязан на Docker-in-Docker, то миграция станет настоящей головной болью. А возможно, и вовсе нецелесообразной.
Так когда же мигрировать? Если ваш сервер общий для разных разработчиков и вам нужна надёжная изоляция. Или когда без компромиссов есть жёсткие требования по безопасности, например, по ФСТЭК/ISO. И, конечно, если вы уже используете RHEL/Rocky 9 — там Podman буквально "родной", встроен в систему.
Установка Podman
# Rocky Linux 9 / RHEL 9
sudo dnf install -y podman podman-compose
# Ubuntu 24.04
sudo apt install -y podman podman-compose
# Проверка
podman version
podman info | grep -i rootless
Для rootless нужны /etc/subuid и /etc/subgid. В свежих дистрибутивах заводятся автоматически при создании пользователя. Проверить:
grep $USER /etc/subuid /etc/subgid
# Должно быть что-то вроде
# /etc/subuid:operator:100000:65536
Docker → Podman: словарь команд
| Docker | Podman | Комментарий |
|---|---|---|
| docker run | podman run | Совместимо на 99% |
| docker ps | podman ps | Одинаково |
| docker build | podman build | Используется buildah внутри |
| docker-compose up | podman-compose up | Или quadlet-файлы |
| docker network | podman network | Под капотом netavark/CNI |
| docker volume | podman volume | Хранилище в ~/.local/share/containers |
Я всегда делаю в ~/.bashrc:
alias docker=podman
alias docker-compose="podman-compose"
Миграция compose-проекта
Берём существующий docker-compose.yml. Большинство работает без правок. Что часто ломается:
- Порты ниже 1024. Rootless не может слушать 80/443 напрямую. Либо переназначайте на 8080/8443 + ставьте nginx на хосте, либо правьте
sysctl net.ipv4.ip_unprivileged_port_start=80. - Bind-mount с абсолютными путями. Из-за user namespace UID внутри и снаружи могут не совпадать. Проверяйте права.
- privileged-контейнеры. В rootless часть флагов ограничена. Перечитайте, нужен ли реально privileged.
cd /opt/app
podman-compose up -d
podman-compose ps
Quadlet: systemd-юниты для контейнеров
Это моя любимая фича Podman 4.4+. Вместо compose-файла описываете контейнер в systemd-юните *.container, и systemd сам поднимает его при старте.
# ~/.config/containers/systemd/nginx.container
[Unit]
Description=Nginx reverse proxy
After=network-online.target
[Container]
Image=docker.io/library/nginx:1.27-alpine
PublishPort=8080:80
Volume=/home/operator/nginx/conf:/etc/nginx/conf.d:ro,Z
AutoUpdate=registry
[Service]
Restart=always
[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user start nginx
journalctl --user -u nginx -f
Плюсы: логи в journalctl, автозапуск через loginctl enable-linger, обновление через podman auto-update по расписанию.
Реальный кейс: мониторинговый стек для производственного холдинга
В октябре 2025 года клиент — металлообработка на 180 рабочих местах — пришёл с задачей: «хотим Grafana + Prometheus + Loki, но служба безопасности запрещает запускать сервисы от root». Идеальный кейс для Podman rootless. Мы создали отдельного пользователя monitor, дали ему subuid 100000:65536, развернули 8 контейнеров через quadlet.
Сроки: 2 рабочих дня на развёртывание, 1 день на интеграцию с экспортёрами на 6 серверах клиента. Стоимость — 54 000 руб. Через полгода заказчик отметил: zero инцидентов безопасности с контейнерами, обновления по расписанию через podman auto-update, единый журнал в journalctl.
Сетевые грабли
В rootless сеть отличается от Docker bridge. Используется slirp4netns или pasta для user-mode networking. Следствия:
- Источник соединений снаружи виден как
10.0.2.100, а не реальный IP клиента. Для nginx логов ставьте--network=pasta:--map-guest-addr,169.254.1.2или используйте реверс-прокси на хосте. - Скорость сети. В rootless-режиме она заметно ниже, чем в root-mode. По нашим собственным тестам, это около 40% потери. Имейте в виду.
- Мульти-хостовые сети (overlay)? Штатной поддержки нет. Придётся обходиться отдельными "костылями" — это не всегда удобно.
Но если мы говорим о высокопроизводительных сервисах — например, о базах данных или видеостримах, тут всё иначе. В таких случаях лучше либо совсем не трогать Docker, либо уж сразу идите на rootful Podman. Полумеры здесь просто не работают.
Миграционный чек-лист
- Что ещё важно? Инвентаризация контейнеров. Нужно чётко понимать, что запущено, какие ресурсы потребляет и какие порты открыты.
- Наш совет: прежде чем делать что-то глобально, обязательно протестируйте миграцию на одном второстепенном сервисе. Поможет выявить большинство проблем заранее.
- Сначала самое главное: ставим Podman. Да, прямо рядом с вашим Docker, пусть пока поживут вместе. Это позволит нам всё протестировать безболезненно. А чтобы всё работало без лишних прав, обязательно создаём нового пользователя для rootless-режима. Безопасность — это важно, не так ли?
- Теперь займёмся файлами `compose`. Просто так перенести их не получится. Нужно адаптировать настройки — особенно внимательно посмотрите на порты, опции `privileged` и `bind-mounts`. В Podman они работают немного иначе, поэтому придётся кое-что подправить, чтобы всё встало на свои места. Это как переезд в новую квартиру: мебель та же, но расставлять надо по-другому.
- Переезд образов (
podman pull) и данных (томов). - Итак, всё готово к запуску! Используем `podman-compose` или современный `quadlet` — смотря что вам ближе. Но главное, не торопитесь. Мы рекомендуем запускать Podman параллельно с Docker на 3–5 дней. За это время вы сможете убедиться, что все сервисы работают стабильно, а ошибок нет. Ведь спешка здесь ни к чему.
- Отлично, тестовый период пройден? Всё работает как часы? Тогда можно с чистой совестью отключать Docker-контейнеры. И, пожалуйста, не забудьте про архивацию данных! Это как собрать вещи после переезда — вдруг что-то понадобится. Лучше перестраховаться, чем потом кусать локти.
- Удаление Docker (если больше не нужен).
- Всё, миграция завершена. Но работа на этом не заканчивается! Чтобы система жила долго и счастливо, настройте автообновление, регулярные бэкапы и, конечно, мониторинг. Мы же не хотим сюрпризов, правда? Пусть всё будет под контролем. Надёжность и стабильность — вот к чему мы стремимся.
Поможем с переходом на Podman
За нашими плечами, между прочим, уже десятки успешных миграций compose-проектов именно на rootless Podman. Мы можем похвастаться более чем 15-летним опытом администрирования корпоративных Linux-инфраструктур. В нашем распоряжении 8 серверов Dell Xeon Platinum 8280 с 40G Mellanox, размещённых в дата-центре МТС Москва для резервного размещения. Кстати, аудит вашей инфраструктуры мы проведём абсолютно бесплатно.
Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш
FAQ — переход с Docker на Podman
- Чем rootless Podman безопаснее Docker?
- Docker-демон запускается от root и эффективно даёт root-доступ всем, кто в группе docker. Podman rootless работает под обычным пользователем с user namespaces — уязвимость в контейнере даёт права пользователя, не root. Нет демона — нет единой точки отказа.
- Podman совместим с Docker CLI?
- Да, alias docker=podman работает для 90% команд: pull, run, ps, exec, logs, build. Отличия — в сетевых командах (podman использует netavark/slirp4netns) и в рабочих каталогах. Скрипты обычно переезжают с минимальными правками.
- Нужен ли podman-compose или лучше сразу quadlet?
- Для быстрой миграции — podman-compose, он читает docker-compose.yml. Для продакшна рекомендую quadlet — systemd-юниты с описанием контейнеров, чистая интеграция с journalctl, автозапуск при перезагрузке.
- Можно ли пробросить порты 80 и 443 в rootless?
- По умолчанию нет — rootless пользователь не имеет права на привилегированные порты. Решения: net.ipv4.ip_unprivileged_port_start=80 в sysctl, setcap, либо reverse proxy (nginx/haproxy) на хосте, а контейнеры слушают 8080/8443.
- Podman поддерживает GPU и CUDA?
- Да, через CDI (Container Device Interface). NVIDIA предоставляет nvidia-container-toolkit с поддержкой Podman. Настраивается чуть сложнее Docker, но работает стабильно на RHEL 9, Rocky 9, Ubuntu 24.04.
