Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Podman: контейнеры без демона на практике

Podman вместо Docker: контейнеры без демона и root-прав

Как работать с Podman: daemonless-архитектура, rootless из коробки, совместимость с Docker CLI и compose, quadlet-юниты systemd и подводные камни миграции.

Прямой ответ

Podman — контейнерный движок от Red Hat с двумя принципиальными отличиями от Docker: без демона (dockerd — постоянно живущий root-процесс, через который идут все операции — единая точка отказа и привилегированная цель атаки; Podman fork'ает контейнеры напрямую от вашего шелла — каждый контейнер — процесс пользователя — «демон умер» как класс проблемы отсутствует) и rootless из коробки (контейнер от обычного uid — без настройки, без группы docker — группа docker = root-эквивалент на хосте через сокет — харднинг-контекст — «rootless по умолчанию» — главный аргумент безопасности Podman); совместимость — практически полная на уровне привычек: alias docker=podman покрывает 95% повседневности (run/build/ps/logs/exec — тот же CLI — образы OCI-совместимы — Docker Hub/registry работают — реестры/теги); различия, которые придётся узнать: (1) pods (группы контейнеров с общим net-namespace — «маленький k8s-под локально» — podman pod create -p 8080:8080 + два контейнера в под — nginx+app делят сеть без линков — k8s-модель мысленно переносится — podman generate kube/podman kube play — YAML туда-обратно — «поиграл локально — унёс в кластер»); (2) systemd-интеграция (quadlet — .container-юниты — контейнер как systemd-сервис — автозапуск/рестарт/логи в journal — на сервере без k8s это главный паттерн — см. ниже; docker — --restart unless-stopped у демона — Podman — у systemd — процессы-культура); (3) rootless-ограничения (порты <1024 — нельзя без настроек (sysctl net.ipv4.ip_unprivileged_port_start=80 или прокси — nginx-паттерн); том-маунты с хоста — по uid-маппингу (userns-механика — «root в контейнере» = ваш uid снаружи — права на volume-файлы удивляют первого дня — :z/:Z-метки SELinux на Fedora/RHEL — иначе access denied); (4) build (buildah внутри — Dockerfile работает как есть — podman build — но BuildKit-специфичные фичи docker (heredoc-синтаксис части) — не всё — multistage переносится, экзотика — проверяем); compose — два пути: podman-compose (python-обёртка — простые стеки) или podman + docker-compose через socket-совместимость (systemctl --user enable --now podman.socket — compose-файлы работают как с docker — композ-практика — большинство dev-стеков стартует без правок); когда Podman выигрывает: сервер без k8s (quadlet-юниты — systemd-нативно), безопасность/rootless-политика («никаких root-демонов на хостах» — комплаенс), Fedora/RHEL-мир (первый класс), CI-джобы (build без привилегированного демона — github-actions — «build образа внутри контейнера CI» — docker-in-docker-боль отсутствует); когда Docker практичнее: экосистемная обвязка (Docker Desktop на маках/виндах — devex, часть tooling'а тестит на docker — локальный стек — команда на docker — switching cost реален), специфичные фичи (BuildKit-экзотика, Swarm-наследие); честный итог: на Linux-серверах 2026 — Podman полноценен и часто предпочтительнее (безопасность+systemd), на рабочих ноутбуках — по вкусу команды — образы/файлы переносимы — выбор-контекст — не религия, а контекст.

Quadlet: контейнер как systemd-сервис

Quadlet (встроен в Podman 4.4+/5.x — генератор systemd-юнитов из .container-файлов): кладём /etc/containers/systemd/app.container — systemctl daemon-reload && systemctl start app — сервис живёт в systemd (Restart=always, journal-логи, зависимости After=network — «docker run -d --restart» + systemd-обвязка — декларативно и нативно); анатомия юнита: [Container] (Image=, ContainerName=, PublishPort=8080:8000, Volume=app-data:/data — именованные тома — хранение, EnvironmentFile= — секреты из env) + [Service] (Restart=on-failure — обычная systemd-секция) + [Install] WantedBy=multi-user.target; пользовательский режим (~/.config/containers/systemd/ + loginctl enable-linger — сервисы юзера без root вообще — «продакшен-паттерн без привилегий»); обновления (Image=registry/app:1.4 → 1.5 — podman pull + systemctl restart app — rollback — вернуть тег — версионирование; auto-update — podman auto-update + таймер — «:latest с автообновлением» — осторожно — тег-стратегии); healthcheck в юните (HealthCmd в [Container] — systemd-зависимости по здоровью — «стартуй B после того, как A healthy» — After=+Requires= — compose-подобные зависимости systemd-средствами); логи — journal (journalctl -u app — ротация — логи-практика — journald-лимиты настройкой — агрегация — Loki/journald-шип); «сервер на трёх сервисах без k8s» — типовой профиль: Postgres+app+nginx как три quadlet-юнита (локальный стек — серверный вариант — ёмкость — когда k8s — оверкилл, а «голый процесс» — уже страшно — quadlet — середина).

Практический сценарий: миграция сервера с docker+compose на podman+quadlet

Контекст: прод-сервер (Ubuntu 24.04, VPS): docker-ce + dockerd (root-демон) + три сервиса в compose (app/nginx/redis) — аудит безопасности: «root-демон с сокетом, группа docker у трёх разработчиков — риск-эскалация» — требование: rootless; миграция (выходные, поэтапно): (1) подготовка — podman 5 из репо, podman.socket для compose-совместимости, sysctl на порты (ip_unprivileged_port_start=80 — nginx без root); (2) перенос compose-стека — сначала как есть (podman-compose up -d — образы те же — реестр — том-пути поправили под userns-маппинг (files на томе принадлежали «внешнему» uid 100000 — chown на маппинг — первая шишка — volume-механика поняли глубже); проработало — но цель не compose, а systemd; (3) quadlet-разложение: app.container (EnvironmentFile=/etc/app.env — секреты), redis.container (Volume=redis-data:/data, HealthCmd=redis-cli ping), nginx.container (PublishPort=80:80, Volume=./conf:/etc/nginx/conf.d:ro,Z — SELinux-метка); зависимости — After=redis.service (nginx не зависит — app ретраит подключение — retry); (4) проверка — systemctl start app redis nginx — journal-логи (структурированные — Loki-шип перенастроили на journald-источник — агрегация); podman unshare ls -l /volume — uid-маппинг сверили — права ок; reboot-тест — всё поднялось (systemd-порядок — healthcheck-культура); (5) нагрузка — p95 не изменился (±2% — бенчмарк-методика — рантайм-оверхед в шум — метрики); (6) docker-ce снесли, группу docker распустили, сокет-файл исчез — поверхность атаки минус root-демон (харднинг — аудитор доволен); находки: (а) nginx-health в compose «работал» через docker-сеть — в quadlet'ах поды/сети явные — поправили на localhost (сети-механика); (б) автообновление образов — podman auto-update.timer — с pin-политикой (обновляем только minor-теги, не latest); (в) CI остался на docker-build (github-actions-раннеры — CI — образы OCI — «собрал docker, запустил podman» — нормально); итог: тот же стек, минус root-демон, плюс systemd-порядок; время — выходные; вывод в ADR: «серверы без k8s — podman+quadlet; ноутбуки — docker/podman по вкусу команды; образы — OCI-нейтральны».

FAQ

Podman полностью заменяет Docker? Для типовых задач разработки/деплоя — да (CLI-совместимость, OCI-образы, compose через socket, build — multistage работает); исключения: Docker Desktop (mac/win — podman-desktop/podman machine — VM-слой у обоих — опыт другой — команды на маках часто остаются на Docker Desktop); BuildKit-специфика (cache mounts/heredoc — часть поддерживается buildah — не всё — «Dockerfile с экзотикой» — проверить сборку до миграции); Swarm (наследие — живым проектам — миграция на k8s/nomad — контекст); сторонний tooling, завязанный на docker API/CLI-специфику (проверить список); практический подход — не «замена одним днём», а «новые серверы — podman, старые — при апгрейде» — техдолг-подход.

Что такое rootless-контейнер и какие у него ограничения? Механика: user namespace маппит внутренний root (uid 0) на непривилегированный внешний (uid 100000+ — userns-основы) — процессы/файлы контейнера принадлежат вашему uid — компрометация контейнера ≠ root на хосте (главный выигрыш — харднинг); ограничения: порты <1024 (sysctl-порог или прокси/порт-маппинг), некоторые операции с сетью/устройствами (NET_ADMIN-подобное — часть недоступна — VPN-контейнеры/privileged-кейсы — останутся root/специфика), производительность отдельных сценариев (rootless-сети — pasta/slirp4netns против root-моста — на высоконагруженных сетевых профилях — measurable — бенчмарк-дисциплина — для веба/API — в шуме), SELinux-метки томов (:z/:Z на RHEL-семье — «permission denied на том» — первый день); docker rootless тоже существует (настраивается — не дефолт) — у Podman — из коробки и первоклассно.

Как запускать контейнеры при старте сервера без докера-демона? Quadlet (раздел выше) — декларативные .container-юниты — systemd управляет (старт/рестарт/логи/зависимости — нативная интеграция); альтернативы: podman generate systemd (старый путь — генерация юнитов из живых контейнеров — вытеснен quadlet'ом), systemd-таймеры для периодики (cron-задачи контейнером — планировщики), podman kube play из k8s YAML (манифесты кластера — локально/серверно — декларативность k8s без k8s); пользовательские сервисы без root — ~/.config/containers/systemd/ + linger — «продакшен без единого root-процесса»; сравнение с docker: у docker — демон+restart-политики (своя мини-система), у podman — «просто systemd» — одна система управления вместо двух — операционная простота — дежурный знает systemctl.

Podman Desktop и podman machine — что это для ноутбука? podman machine — лёгкая VM с Linux (mac/win — контейнерам нужно Linux-ядро — VM-слой неизбежен у всех — docker desktop — та же VM — разница в обвязке/лицензии); Podman Desktop — GUI (образы/контейнеры/поды/kube-play — docker-desktop-аналог — бесплатно/open source — docker desktop — платно для крупных компаний — лицензионный аргумент миграции реален); на Linux-ноутбуке — machine не нужен (podman нативен — локальный стек — rootless из коробки); практические заметки: compose-стеки через podman.socket — работают (dev-стек Postgres/Redis/MinIO — MinIO — стартует без правок); тома — скорость на mac/win через VM-слой (bind-mount производительность — боль всех VM-подходов — volume против bind — хранение); вывод: «podman на ноуте» — рабочий вариант, выбор — по команде/лицензии/привычке — технически паритет.

Источники: документация Podman (docs.podman.io, quadlet units), Red Hat sysadmin — ссылки в шапке.