Podman вместо Docker: rootless-контейнеры в продакшене

Зачем переходить с Docker на Podman

Docker работает через центральный демон dockerd, запущенный от root. Любая уязвимость в демоне даёт атакующему полный контроль над хостом. Podman решает эту проблему архитектурно: нет демона — каждый контейнер запускается как отдельный процесс, а режим rootless позволяет запускать контейнеры от обычного пользователя без привилегий.

Podman поддерживает тот же формат образов (OCI), совместим с Dockerfile и большинством команд Docker (можно создать алиас alias docker=podman). Для оркестрации используется podman-compose или встроенная поддержка pods — аналог Kubernetes pods.

В корпоративной среде переход на Podman оправдан по нескольким причинам: требования безопасности (CIS Benchmark, PCI DSS), отказ от единой точки отказа в лице демона, нативная интеграция с systemd для управления жизненным циклом контейнеров и поддержка в RHEL/CentOS/AlmaLinux из коробки.

Установка Podman и базовая настройка

На RHEL-based дистрибутивах Podman входит в стандартные репозитории:

# RHEL 9 / AlmaLinux 9
sudo dnf install -y podman podman-compose

# Ubuntu 22.04
sudo apt install -y podman podman-compose

# Проверяем версию
podman --version
podman info

Для rootless-режима необходимо настроить пользовательские namespaces:

# Проверяем, что subordinate UID/GID настроены
grep $USER /etc/subuid
grep $USER /etc/subgid

# Если записей нет — добавляем
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER

# Инициализируем пользовательское пространство
podman system migrate

Конфигурация реестров образов

Podman по умолчанию ищет образы в нескольких реестрах. Настроим приоритет в ~/.config/containers/registries.conf:

unqualified-search-registries = ["docker.io", "quay.io", "ghcr.io"]

[[registry]]
location = "registry.company.ru"
insecure = false

[[registry.mirror]]
location = "mirror.company.ru"

Для приватного реестра выполните вход:

podman login registry.company.ru
# Credentials хранятся в ~/.local/share/containers/auth.json

Миграция контейнеров с Docker на Podman

Основные команды Podman идентичны Docker. Разница проявляется в деталях:

# Запуск контейнера — синтаксис идентичен
podman run -d --name nginx -p 8080:80 nginx:alpine

# Список контейнеров
podman ps -a

# Просмотр логов
podman logs -f nginx

# Выполнение команды внутри
podman exec -it nginx sh

Для миграции docker-compose файлов используйте podman-compose:

# Запуск стека из docker-compose.yml
podman-compose up -d

# Остановка
podman-compose down

Есть нюансы, требующие внимания при миграции:

  • Сеть: в rootless-режиме порты ниже 1024 недоступны без дополнительной настройки (sysctl net.ipv4.ip_unprivileged_port_start=80)
  • Volumes: пути к томам должны быть доступны пользователю, от которого запущен Podman
  • Сокет: вместо /var/run/docker.sock используется /run/user/$(id -u)/podman/podman.sock

Перенос образов без реестра

Если нужно перенести образ с Docker на Podman на одном хосте:

# Экспорт из Docker
docker save myapp:latest | gzip > myapp.tar.gz

# Импорт в Podman
podman load -i myapp.tar.gz
podman images | grep myapp

Podman Pods: группировка контейнеров

Pod — группа контейнеров, разделяющих сетевое пространство (как в Kubernetes). Контейнеры внутри пода общаются через localhost:

# Создаём под с проброшенным портом
podman pod create --name webapp -p 8080:80

# Добавляем Nginx как фронтенд
podman run -d --pod webapp --name web nginx:alpine

# Добавляем PHP-FPM как бэкенд
podman run -d --pod webapp --name php php:8.2-fpm

# Nginx обращается к PHP-FPM по localhost:9000
# Список контейнеров в поде
podman pod ps
podman ps --pod

Поды удобны для микросервисных связок: веб-сервер + приложение + sidecar-контейнер для логирования. При этом весь под можно остановить, запустить или удалить одной командой:

podman pod stop webapp
podman pod start webapp
podman pod rm -f webapp

Интеграция с systemd: автозапуск контейнеров

Главное преимущество Podman перед Docker в корпоративной среде — нативная интеграция с systemd. Вместо перезапуска демона контейнеры управляются стандартными юнитами:

# Генерируем systemd-юнит из работающего контейнера
podman generate systemd --new --name nginx --files

# Для rootless — помещаем в пользовательскую директорию
mkdir -p ~/.config/systemd/user/
mv container-nginx.service ~/.config/systemd/user/

# Включаем и запускаем
systemctl --user daemon-reload
systemctl --user enable --now container-nginx.service

# Проверяем статус
systemctl --user status container-nginx.service

Для автозапуска юнитов после перезагрузки без логина пользователя:

sudo loginctl enable-linger $USER

Quadlet: декларативные юниты в Podman 4.4+

Podman 4.4 ввёл Quadlet — декларативное описание контейнеров прямо в systemd-формате. Файл ~/.config/containers/systemd/webapp.container:

[Unit]
Description=Web Application
After=network-online.target

[Container]
Image=docker.io/library/nginx:alpine
PublishPort=8080:80
Volume=/srv/www:/usr/share/nginx/html:ro,Z
Environment=TZ=Europe/Moscow

[Service]
Restart=always
TimeoutStartSec=60

[Install]
WantedBy=default.target

После создания файла выполните systemctl --user daemon-reload и запустите: systemctl --user start webapp. Quadlet заменяет ручную генерацию юнитов и является рекомендованным способом управления контейнерами в продакшене.

Безопасность rootless-контейнеров

Rootless Podman обеспечивает несколько уровней изоляции:

  • User namespaces: root внутри контейнера маппится на непривилегированного пользователя хоста (UID 100000+)
  • Нет демона: компрометация одного контейнера не затрагивает остальные
  • SELinux: автоматическая маркировка томов суффиксом :Z или :z
  • Seccomp: ограничение системных вызовов по умолчанию

Дополнительные меры для усиления безопасности:

# Запуск с минимальными capabilities
podman run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx

# Запрет эскалации привилегий
podman run --security-opt=no-new-privileges nginx

# Только чтение файловой системы
podman run --read-only --tmpfs /tmp nginx

Для аудита образов используйте podman image inspect и сторонние сканеры (Trivy, Grype):

# Сканирование образа на уязвимости
trivy image nginx:alpine

Сетевые режимы и хранилища

Podman поддерживает несколько сетевых драйверов. В rootless-режиме по умолчанию используется slirp4netns (медленнее), в версии 4.0+ — pasta (быстрее):

# Создание пользовательской сети
podman network create --subnet 10.89.0.0/24 mynet

# Запуск контейнера в сети
podman run -d --network mynet --name db postgres:16
podman run -d --network mynet --name app myapp:latest

# Контейнеры общаются по имени
# app может подключиться к db:5432

Для хранения данных используйте именованные тома:

# Создание тома
podman volume create pgdata

# Использование в контейнере
podman run -d --name db -v pgdata:/var/lib/postgresql/data postgres:16

# Инспекция тома
podman volume inspect pgdata

Часто задаваемые вопросы

На уровне CLI — практически полностью. Podman поддерживает те же команды и формат образов (OCI). Однако есть различия: отсутствие демона означает, что приложения, обращающиеся к Docker socket, требуют настройки совместимого сокета (podman system service). Docker Swarm не поддерживается.

Да, двумя способами: через podman-compose (Python-обёртка) или через оригинальный docker-compose с включённым Podman-сокетом: systemctl --user start podman.socket и переменной DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock.

Podman может генерировать Kubernetes YAML из работающих подов (podman generate kube) и запускать поды из YAML (podman play kube). Это упрощает разработку: локально тестируете в Podman, затем деплоите тот же манифест в Kubernetes.

Основная потеря — в сетевом стеке: slirp4netns добавляет 10–15% latency. С драйвером pasta (Podman 4.0+) разница сокращается до 2–5%. Производительность файловых операций и CPU идентична root-режиму.

Нужна помощь с настройкой?

Специалисты АйТи Фреш помогут с внедрением и настройкой — 15+ лет опыта, обслуживание от 15 000 ₽/мес

📞 Связаться с нами
#podman#rootless контейнеры#podman vs docker#миграция на podman#podman compose#контейнеры без root#podman systemd#безопасность контейнеров
Комментарии 0

Оставить комментарий

загрузка...