Hướng dẫn sử dụng Podman Compose trên Fedora: Thay thế Docker Compose để quản lý ứng dụng đa container rootless

Fedora tutorial - IT technology blog
Fedora tutorial - IT technology blog

Vấn đề khi có nhiều container cần phối hợp

Chạy một container đơn lẻ với podman run thì đơn giản. Rắc rối bắt đầu khi ứng dụng cần 3–4 container phối hợp nhau — web app, database, cache, reverse proxy. Network phải tạo tay. Thứ tự khởi động phải canh đúng. Biến môi trường phải truyền đúng chỗ, volume phải mount đồng bộ. Deploy lần đầu thì xong được. Lần thứ hai, hoặc chuyển sang máy khác, là mất nửa buổi.

Mình dùng Fedora làm máy development chính đã 2 năm — khá hài lòng với tốc độ cập nhật package, Podman thường đi trước các distro khác cả vài tháng. Nhưng chính vì Fedora đẩy Podman thay Docker, nhiều người gặp câu hỏi thực tế: file docker-compose.yml cũ giờ chạy thế nào?

Bốn cách để orchestrate nhiều container trên Fedora

Cách 1: Giữ nguyên Docker Compose

Cài Docker Engine lên Fedora vẫn được, không ai cấm. Docker Compose chạy bình thường, file compose không cần đụng vào.

Nhưng có vài điểm khó chịu. Docker daemon cần chạy root — cộng thêm một systemd service riêng phải quản lý. Fedora cũng không còn ship Docker trong repo chính thức, tức là mỗi lần nâng Fedora version phải kiểm tra lại repo Docker riêng. Mình từng gặp Docker daemon crash sau khi upgrade Fedora 38 → 39 vì xung đột cgroup v2 — mất gần 2 tiếng mới debug ra nguyên nhân.

Cách 2: Podman Pods — native nhưng verbose

Podman hỗ trợ khái niệm “pod” — nhóm container dùng chung network namespace, tương tự Kubernetes pod. Bạn tạo pod rồi add container vào:

podman pod create --name myapp -p 8080:80
podman run -d --pod myapp nginx
podman run -d --pod myapp postgres:15

Vấn đề là không có file config nào để version control. Muốn tái tạo lại stack phải gõ lại toàn bộ lệnh từ đầu. Nếu bạn đã quen workflow khai báo kiểu docker-compose.yml, cách này sẽ cảm giác như thụt lùi.

Cách 3: Quadlet — systemd-native cho production

Từ Podman 4.4+ (Fedora 38+), Quadlet cho phép viết file .container.pod trong ~/.config/containers/systemd/, systemd tự generate unit file. Rất production-ready, tích hợp tốt với journalctl và restart policy đầy đủ.

Nhưng để dùng được Quadlet, bạn phải học cú pháp mới từ đầu — khác hoàn toàn với docker-compose.yml. Nếu đang có 10–15 project dùng compose file, migrate hết sang Quadlet không phải việc một buổi.

Cách 4: Podman Compose — điểm cân bằng thực dụng

Podman Compose là tool Python chạy file docker-compose.yml bằng Podman backend thay vì Docker. Không cần daemon root, hỗ trợ rootless hoàn toàn, cú pháp giữ nguyên so với Docker Compose.

So sánh bốn approach

Approach Rootless Tương thích compose file Systemd integration Learning curve
Docker Compose ❌ Root daemon ✅ 100% Thủ công Thấp
Podman Pods ❌ Cú pháp khác Thủ công Trung bình
Quadlet ❌ Cần migrate ✅ Native Cao
Podman Compose ✅ ~90% Có thể wrap Thấp

Podman Compose không hỗ trợ 100% spec — một số tính năng như extends, profiles phức tạp, hay một số deploy option có thể thiếu. Nhưng cho 90% use case thông thường, nó chạy ổn mà không cần sửa gì.

Cài đặt Podman Compose trên Fedora

Fedora có Podman Compose trong repo chính thức từ Fedora 36+:

sudo dnf install podman-compose
podman-compose --version

Nếu muốn version mới nhất từ PyPI:

pip install --user podman-compose

Triển khai thực tế: Web app + PostgreSQL + Redis

Tạo cấu trúc project

mkdir ~/myapp && cd ~/myapp
mkdir -p app nginx/conf.d

Viết docker-compose.yml

version: '3.8'

services:
  web:
    image: python:3.11-slim
    working_dir: /app
    volumes:
      - ./app:/app:Z
    command: python -m http.server 8000
    depends_on:
      - db
      - cache
    environment:
      - DATABASE_URL=postgresql://user:password@db:5432/mydb
      - REDIS_URL=redis://cache:6379

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydb
    volumes:
      - pgdata:/var/lib/postgresql/data

  cache:
    image: redis:7-alpine
    command: redis-server --save 60 1

  nginx:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
    depends_on:
      - web

volumes:
  pgdata:

File cấu hình nginx

# nginx/conf.d/default.conf
server {
    listen 80;
    location / {
        proxy_pass http://web:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Các lệnh cơ bản

# Khởi động toàn bộ stack
podman-compose up -d

# Xem log real-time
podman-compose logs -f

# Kiểm tra trạng thái
podman-compose ps

# Dừng và xóa container (giữ volume)
podman-compose down

# Dừng và xóa cả volume data
podman-compose down -v

Những điểm dễ vấp khi chạy rootless trên Fedora

Volume mount và SELinux

Fedora chạy SELinux enforcing theo mặc định. Khi mount thư mục host vào container, phải thêm label :Z (relabel riêng cho container này) hoặc :z (shared giữa nhiều container):

volumes:
  - ./app:/app:Z          # Relabel riêng cho container này
  - ./config:/etc/app:z   # Shared — nhiều container cùng đọc

Thiếu label này là nguyên nhân số một của lỗi “Permission denied” khi chạy Podman trên Fedora. Container start xong xuôi, log sạch bóng, nhưng app bên trong cứ báo lỗi đọc file — SELinux đang chặn ở background mà không có dòng log nào rõ ràng.

Port dưới 1024

Rootless container không bind được port nhỏ hơn 1024 theo mặc định. Cho môi trường dev, dùng port cao hơn là đủ. Nếu thực sự cần port 80/443:

# Hạ ngưỡng port cho user thường (cần root một lần)
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee /etc/sysctl.d/99-podman-ports.conf
sudo sysctl --system

Tự động start khi reboot

Podman Compose không tích hợp systemd sẵn như Quadlet, nhưng có thể wrap bằng user service:

mkdir -p ~/.config/systemd/user

cat > ~/.config/systemd/user/myapp.service << 'EOF'
[Unit]
Description=My App Stack
After=default.target

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=%h/myapp
ExecStart=/usr/bin/podman-compose up -d
ExecStop=/usr/bin/podman-compose down
TimeoutStartSec=0

[Install]
WantedBy=default.target
EOF

systemctl --user enable --now myapp.service

# Cho service chạy khi user chưa đăng nhập
loginctl enable-linger $USER

Khi nào nên chuyển sang Quadlet

Podman Compose phù hợp cho development và staging. Còn production trên Fedora Server? Quadlet là câu chuyện khác hẳn: log thẳng vào systemd journal, dependency management qua unit files, restart tự động không cần script wrapper bên ngoài.

Tin vui là từ Fedora 40, có tool podlet tự động convert file compose sang Quadlet:

sudo dnf install podlet
podlet compose docker-compose.yml

Nó generate ra file .container.network sẵn dùng, giúp migrate mà không phải viết lại từ đầu.

Tổng kết

Cho môi trường development trên Fedora, Podman Compose là điểm khởi đầu hợp lý nhất. Rootless, không cần daemon, chạy được 90% file compose hiện tại mà không sửa gì. Khi project lớn lên và cần độ ổn định production — restart policy đàng hoàng, journald, dependency graph — thì Quadlet mới đáng đầu tư. Lúc đó, podlet lo phần convert, bạn chỉ cần review lại output là xong.

Share: