Podman hay Docker? Góc nhìn từ người dùng Fedora hàng ngày
Mình dùng Fedora làm máy development chính đã 2 năm và khá hài lòng với tốc độ cập nhật package. Một trong những thứ mình chuyển sang sớm nhất là Podman — không phải vì trend, mà vì Fedora đã cài sẵn và không cần chạy daemon root. Nhưng thực tế workflow quản lý images với Podman có gì khác Docker không? Câu trả lời: gần như giống hệt về mặt lệnh, nhưng kiến trúc bên dưới khác nhau hoàn toàn.
Hôm nay mình không nói lý thuyết nữa. So sánh thẳng 3 cách quản lý images, chỉ điểm khác biệt thực tế, rồi demo build/push/pull ngay trên máy Fedora đang chạy.
3 Approach quản lý container images trên Fedora
Approach 1: Docker Engine cài thêm vào Fedora
Cách này vẫn dùng được — thêm repo Docker CE, cài docker-ce, chạy daemon. Nhưng có vài vấn đề thực tế:
- Docker daemon chạy root, nghĩa là mọi container bạn chạy đều có tiềm năng leo quyền lên host
- Fedora cập nhật kernel nhanh, đôi khi Docker CE chưa kịp hỗ trợ phiên bản mới nhất
- Conflict với Podman nếu cả hai cùng dùng
/var/run/docker.sock
Mình đã thử cài Docker CE song song với Podman một thời gian — kết quả là headache không đáng có.
Approach 2: Podman với Podman Desktop
Podman Desktop là GUI app, cài qua Flatpak hoặc RPM. Nếu bạn thích click hơn gõ lệnh, đây là lựa chọn ổn — có dashboard quản lý images, containers, kết nối registry, và tích hợp Docker Compose compatibility layer sẵn.
Nhưng mình dừng lại ở đó. Thêm một lớp abstraction là thêm một lớp có thể fail — khi lỗi xảy ra, bạn phải mò xem GUI đang gọi lệnh gì bên dưới, debugging mất gấp đôi thời gian.
Approach 3: Podman CLI thuần — Cách mình đang dùng
Đây là cách mình chọn cho môi trường development và CI pipeline. Lý do đơn giản:
- Rootless by default — container chạy dưới user namespace của bạn
- Không có daemon — mỗi lệnh
podmanlà một process độc lập, crash-safe - OCI compliant — images build bằng Podman tương thích hoàn toàn với Docker registry
- Buildah tích hợp sẵn — build images không cần Docker daemon
Phân tích ưu nhược điểm
| Tiêu chí | Docker CE | Podman Desktop | Podman CLI |
|---|---|---|---|
| Rootless | Partial (Docker rootless mode) | Có | Có (mặc định) |
| Daemon | Cần | Không | Không |
| Fedora compatibility | Cần thêm repo | Tốt | Cài sẵn |
| CI/CD friendly | Tốt | Kém | Rất tốt |
| Learning curve | Thấp (quen rồi) | Thấp | Thấp nếu biết Docker |
Nếu đang làm trên Fedora mà chưa bị ràng buộc bởi tool nào đó yêu cầu Docker daemon — hãy stick với Podman CLI. Ít thứ có thể fail, ít thứ phải maintain.
Triển khai thực tế: Build, Push, Pull với Podman trên Fedora
Bước 1: Kiểm tra Podman đã có sẵn
Trên Fedora 38+, Podman cài sẵn. Kiểm tra nhanh:
podman --version
# Podman version 5.x.x
podman info | grep -E 'rootless|cgroup'
# rootless: true
Nếu chưa có:
sudo dnf install -y podman
Bước 2: Viết Containerfile (tương đương Dockerfile)
Podman dùng Containerfile hoặc Dockerfile — cả hai đều được. Mình hay dùng tên Containerfile để phân biệt rõ đây không phải Docker workflow.
FROM fedora:40
LABEL maintainer="[email protected]"
LABEL version="1.0"
RUN dnf update -y && \
dnf install -y python3 python3-pip && \
dnf clean all
WORKDIR /app
COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python3", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Bước 3: Build image
# Build từ Containerfile trong thư mục hiện tại
podman build -t myapp:1.0 .
# Build từ file cụ thể
podman build -f Containerfile -t myapp:1.0 .
# Build với build args
podman build --build-arg APP_ENV=production -t myapp:1.0 .
# Xem image vừa build
podman images
Output của podman images trông như thế này:
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/myapp 1.0 a3f8c21d9e4b 2 minutes ago 412 MB
registry.fedoraproject.org/fedora 40 8f3a1bc2d5e9 3 weeks ago 182 MB
Lưu ý: Podman dùng prefix localhost/ cho images local, khác với Docker không có prefix. Chi tiết nhỏ nhưng hay gây nhầm khi mới chuyển sang.
Bước 4: Tag image trước khi push
Để push lên registry (Docker Hub, Quay.io, GitHub Container Registry…), cần tag đúng format:
# Tag cho Docker Hub
podman tag localhost/myapp:1.0 docker.io/yourusername/myapp:1.0
podman tag localhost/myapp:1.0 docker.io/yourusername/myapp:latest
# Tag cho GitHub Container Registry
podman tag localhost/myapp:1.0 ghcr.io/yourusername/myapp:1.0
# Tag cho Quay.io
podman tag localhost/myapp:1.0 quay.io/yourusername/myapp:1.0
Bước 5: Login và Push lên registry
# Login Docker Hub
podman login docker.io
# Username: yourusername
# Password: yourpassword_or_token
# Login GitHub Container Registry (dùng Personal Access Token)
echo $GITHUB_TOKEN | podman login ghcr.io -u yourusername --password-stdin
# Push image
podman push docker.io/yourusername/myapp:1.0
podman push docker.io/yourusername/myapp:latest
Credentials được lưu trong ~/.config/containers/auth.json — không phải ~/.docker/config.json như Docker. Tuy nhiên Podman cũng đọc được file của Docker nếu cần.
Bước 6: Pull image từ registry
# Pull từ Docker Hub (explicit)
podman pull docker.io/yourusername/myapp:1.0
# Pull từ Fedora registry (ví dụ)
podman pull registry.fedoraproject.org/fedora:40
# Pull với chỉ định platform (arm64 cho M1/M2 Mac nếu build cross-platform)
podman pull --platform linux/amd64 docker.io/yourusername/myapp:1.0
# Xem tất cả images sau khi pull
podman images
Bước 7: Quản lý images — dọn dẹp và inspect
Skip phần này cho đến khi disk báo 95% full là kinh nghiệm của nhiều người. Đừng để đến lúc đó:
# Xem chi tiết image
podman inspect myapp:1.0
# Xem history của image (các layer)
podman history myapp:1.0
# Xóa image cụ thể
podman rmi localhost/myapp:1.0
# Xóa tất cả images không dùng (dangling)
podman image prune
# Xóa toàn bộ images không có container nào dùng
podman image prune -a
# Xem dung lượng đang chiếm
podman system df
Một số tip thực tế khi dùng Podman trên Fedora
Dùng registries.conf để tránh gõ full registry path
File /etc/containers/registries.conf cho phép cấu hình unqualified-search-registries. Mình không khuyến khích sửa file system — thay vào đó tạo override ở user level cho an toàn:
mkdir -p ~/.config/containers
cat > ~/.config/containers/registries.conf << 'EOF'
unqualified-search-registries = ["docker.io", "quay.io", "registry.fedoraproject.org"]
EOF
Build multi-stage để giảm image size
# Stage 1: Build
FROM fedora:40 AS builder
RUN dnf install -y golang
WORKDIR /src
COPY . .
RUN go build -o myapp .
# Stage 2: Runtime (minimal)
FROM fedora-minimal:40
COPY --from=builder /src/myapp /usr/local/bin/myapp
CMD ["/usr/local/bin/myapp"]
Con số thực tế: một app Go nếu giữ nguyên môi trường build thường nặng 700–900MB. Với multi-stage, runtime image chỉ còn 40–80MB — tiết kiệm hơn 90% dung lượng registry và thời gian pull.
Lưu và load image không qua registry (offline transfer)
# Export image ra file tar
podman save -o myapp-1.0.tar localhost/myapp:1.0
# Nén lại nếu cần transfer
gzip myapp-1.0.tar
# Load trên máy khác
podman load -i myapp-1.0.tar.gz
Cách này mình dùng khá nhiều khi deploy lên server không có kết nối internet ra ngoài — build trên máy dev, save thành file, scp lên server, load vào là xong.
Kết
Podman trên Fedora là combo tự nhiên — không cần cài thêm, không cần daemon, rootless mặc định. Workflow build/push/pull gần như giống Docker hoàn toàn, chỉ khác ở một vài chi tiết nhỏ như prefix localhost/ hay đường dẫn auth config. Sau vài ngày dùng quen là không thấy khác biệt gì đáng kể so với Docker, nhưng lại bớt được một đống overhead không cần thiết.
Team đang có CI/CD dùng Docker thì migrate cũng không đau — mình đã thử với vài repo và hầu hết chỉ cần thay docker thành podman trong script là xong. Phần còn lại chủ yếu là fix đường dẫn auth config.

