Virtualization

Chạy container không cần root với Podman thay Docker

SSH vào VPS, bạn vừa cài Docker xong thì nhận ra daemon Docker chạy với quyền root. Chỉ cần một container bị lỗ hổng, kẻ tấn công có thể leo thang lên toàn bộ máy chủ. Đó là rủi ro mà nhiều sysadmin chấp nhận trong nhiều năm. Podman sinh ra để giải quyết chính vấn đề này: chạy container ở chế độ rootless, tiến trình container thuộc về user thường, không phải root. Bài này hướng dẫn bạn cài Podman trên Ubuntu 24.04 LTS, chuyển workflow từ Docker sang Podman và cấu hình để container tự khởi động cùng hệ thống bằng systemd.

Tóm tắt nhanh

  • Podman là giải pháp thay thế Docker, không cần daemon chạy nền, hỗ trợ rootless container từ phiên bản 4.0.
  • Câu lệnh Podman tương thích phần lớn với Docker: podman run, podman ps, podman build thay cho docker ....
  • Container rootless của Podman mặc định dùng slirp4netns cho mạng, cần mở port bằng flag -p như Docker.
  • Podman tích hợp systemd qua podman generate systemd hoặc quadlet (file .container), giúp container chạy như service khi reboot.

Yêu cầu trước khi bắt đầu

  • Một VPS chạy Ubuntu 24.04 LTS (bài này cũng áp dụng được cho Debian 12, AlmaLinux 9 với lệnh tương ứng).
  • User sudo non-root để cài đặt và chạy container.
  • Hiểu cơ bản về container và lệnh Docker (nếu bạn đã quen Docker thì chuyển sang Podman rất nhanh).
  • Port cần thiết cho container, ví dụ 8080 cho web, mở trên firewall nếu dùng ufw hoặc firewalld.

Vì sao nên chuyển từ Docker sang Podman?

Docker dùng kiến trúc client-server. Một daemon dockerd chạy với quyền root, nhận lệnh từ client và quản lý toàn bộ container. Nếu daemon bị khai thác, attacker có quyền root trên host. Podman không có daemon trung tâm. Mỗi tiến trình podman hoạt động độc lập, container chạy dưới user hiện tại nhờ cơ chế user namespace của Linux kernel. Khi bạn chạy podman run với user thường, tiến trình trong container ánh xạ sang một UID khác trên host, thường là UID rất lớn (ví dụ 100000+). Kể cả khi container bị chiếm quyền, kẻ tấn công cũng chỉ có quyền của user thường đó, không phải root.

Podman tương thích với chuẩn OCI (Open Container Initiative), nghĩa là image từ Docker Hub chạy được bình thường. Lệnh podman được thiết kế để thay thế trực tiếp docker: podman pull, podman build, podman network đều có. Nếu bạn đã viết file docker-compose.yml, dùng podman-compose hoặc podman play kube để chạy. Với một VPS dùng để chạy vài container nhỏ, bỏ daemon Docker giúp giảm một phần bộ nhớ và loại bỏ một tiến trình chạy quyền root.

Có một điểm cần nói rõ: Docker cũng hỗ trợ rootless mode từ bản 19.03, nhưng cách triển khai phức tạp hơn, cần cài thêm slirp4netns, fuse-overlayfs và phải khởi động daemon theo user. Podman làm điều này mặc định, không cấu hình thêm. Với người mới hoặc người muốn đơn giản, Podman dễ tiếp cận hơn.

Bước 1 - Cài đặt Podman trên Ubuntu 24.04

Podman có trong kho lưu trữ chính thức của Ubuntu 24.04. Cập nhật package và cài đặt:

sudo apt update
sudo apt install podman -y

Kiểm tra phiên bản đã cài:

podman --version

Output mong đợi dạng podman version 4.9.3 hoặc mới hơn. Bản 4.x hỗ trợ đầy đủ rootless container và quadlet. Nếu bạn dùng AlmaLinux 9, lệnh cài là sudo dnf install podman.

Sau khi cài, kiểm tra xem user hiện tại có chạy container được không. Lệnh sau chạy container hello-world:

podman run hello-world

Nếu lần đầu chạy, Podman sẽ tải image về. Bạn thấy thông báo giới thiệu Podman hoạt động đúng. Không cần thêm user vào nhóm nào, không cần logout/login lại. Đây là khác biệt lớn so với Docker, nơi bạn phải thêm user vào nhóm docker để tránh lỗi permission denied.

Bước 2 - Cấu hình container rootless và mạng

Container rootless của Podman không có quyền tạo network bridge như Docker. Mặc định Podman dùng slirp4netns, một tiến trình user-space giả lập mạng TCP/IP. Container có IP riêng trong dải 10.0.2.0/24, nhưng không truy cập trực tiếp từ ngoài. Muốn expose port, bạn dùng flag -p giống Docker:

podman run -d --name web -p 8080:80 nginx

Lệnh này chạy container Nginx, map port 8080 trên host vào port 80 trong container. Kiểm tra bằng:

curl -I http://localhost:8080

Kết quả trả về HTTP/1.1 200 OK từ Nginx. Lưu ý, port dưới 1024 (như 80, 443) cần quyền root. Nếu bạn muốn container lắng nghe port 80, phải dùng sudo podman run hoặc cấu hình sysctl net.ipv4.ip_unprivileged_port_start=80. Cách đơn giản nhất là dùng port trên 1024 và đặt reverse proxy Nginx trước mặt, việc này cũng tốt hơn cho bảo mật.

Kiểm tra container đang chạy:

podman ps

Output hiện CONTAINER ID, IMAGE, COMMAND, CREATED, STATUS, PORTS, NAMES giống Docker. Dừng và xóa container:

podman stop web
podman rm web

Bước 3 - Chuyển workflow Docker Compose sang Podman

Nếu bạn đã quen viết docker-compose.yml, không cần chuyển hẳn sang Podman ngay. Cài podman-compose bằng pip hoặc package manager:

sudo apt install podman-compose -y

File cấu hình giữ nguyên cú pháp. Ví dụ file docker-compose.yml chạy Nginx và Redis:

version: "3.8"
services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"
  redis:
    image: redis:7-alpine

Chạy bằng lệnh:

podman-compose up -d

podman-compose đọc file và tạo container qua Podman. Kiểm tra:

podman ps

Bạn thấy hai container webredis đang chạy. Lưu ý podman-compose có một số hạn chế so với Docker Compose v2, ví dụ không hỗ trợ đầy đủ biến môi trường trong file .env ở một số phiên bản. Với cấu hình phức tạp, dùng podman play kube hoặc quadlet sẽ ổn định hơn.

Nếu bạn muốn dùng Docker Compose thật sự, có thể cài plugin docker-compose riêng và trỏ nó tới Podman bằng socket. Nhưng cách này rườm rà. Với hầu hết dự án, podman-compose đủ dùng.

Bước 4 - Chạy Podman như service với systemd (quadlet)

Container chạy bằng podman run sẽ tắt khi bạn logout hoặc VPS reboot. Podman cung cấp cơ chế quadlet, cho phép bạn mô tả container bằng file .container và systemd quản lý vòng đời. Đây là cách "chuẩn" để chạy container production trên Podman.

Đầu tiên tạo thư mục cho quadlet của user:

mkdir -p ~/.config/containers/systemd

Tạo file web.container:

nano ~/.config/containers/systemd/web.container

Nội dung file:

[Unit]
Description=Nginx container

[Container]
Image=docker.io/library/nginx:latest
PublishPort=8080:80

[Service]
Restart=always

[Install]
WantedBy=default.target

Reload systemd và kích hoạt service:

systemctl --user daemon-reload
systemctl --user enable --now web.service

Kiểm tra trạng thái:

systemctl --user status web.service

Quan trọng: service user chỉ chạy khi bạn đăng nhập. Để container chạy từ khi VPS boot mà không cần đăng nhập, kích hoạt "lingering" cho user:

sudo loginctl enable-linger $USER

Sau lệnh này, container Nginx tự khởi động cùng hệ thống và tự restart nếu crash. Đây là cách đáng tin cậy hơn nhiều so với việc chạy container trong screen hay tmux.

So sánh Podman và Docker

Tiêu chíPodmanDocker
Kiến trúcDaemonless, mỗi lệnh độc lậpClient-server, daemon chạy nền
Rootless containerHỗ trợ mặc định, dễ dùngCó nhưng cấu hình phức tạp hơn
Bảo mậtContainer chạy dưới user thường, giảm rủi ro leo thangDaemon chạy root, rủi ro cao hơn nếu bị khai thác
Tương thích Docker HubCó, chuẩn OCI
Docker ComposeDùng podman-compose hoặc quadletHỗ trợ chính thức
Hệ sinh thái và tài liệuMạnh, cộng đồng đang phát triểnRất lớn, nhiều tài liệu hơn

Nhìn vào bảng trên, Podman thắng ở khía cạnh bảo mật và đơn giản khi chạy rootless. Docker vẫn mạnh hơn về hệ sinh thái công cụ xung quanh, đặc biệt là Docker Compose và các tích hợp CI/CD. Với một VPS cá nhân chạy vài container, mình nghiêng về Podman. Với môi trường doanh nghiệp có sẵn pipeline Docker, việc chuyển đổi cần cân nhắc chi phí.

Xử lý lỗi thường gặp

Lỗi "cannot re-exec process" khi chạy rootless

Lỗi này thường do thiếu slirp4netns hoặc user namespace bị giới hạn. Cài thêm package:

sudo apt install slirp4netns fuse-overlayfs -y

Nếu vẫn lỗi, kiểm tra xem kernel có bật user namespace không:

cat /proc/sys/user/max_user_namespaces

Nếu kết quả là 0, bật lên:

sudo sysctl -w user.max_user_namespaces=15000

Để áp dụng lâu dài, thêm dòng user.max_user_namespaces=15000 vào /etc/sysctl.conf rồi chạy sudo sysctl -p.

Container không truy cập được internet

Kiểm tra cấu hình DNS trong file /etc/containers/containers.conf hoặc dùng flag --dns khi chạy:

podman run -d --dns 8.8.8.8 --name test alpine sleep 3600

Nếu mạng chính có vấn đề, kiểm tra slirp4netns có chạy không:

ps aux | grep slirp4netns

Thiếu tiến trình này nghĩa là chưa cài slirp4netns hoặc cài chưa đúng.

Lỗi "unable to find user namespace" trên AlmaLinux

Trên RHEL/AlmaLinux, cần bật quyền cho user namespace:

sudo sysctl -w kernel.unprivileged_userns_clone=1

Thêm vào /etc/sysctl.conf để giữ sau reboot.

Câu hỏi thường gặp

Podman có tương thích hoàn toàn với Docker không?

Phần lớn lệnh và image tương thích. Image từ Docker Hub chạy bình thường vì Podman tuân theo chuẩn OCI. Lệnh cơ bản như run, build, ps giống nhau. Khác biệt nằm ở khía cạnh nâng cao: Docker Compose dùng plugin riêng, Podman dùng podman-compose hoặc quadlet.

Podman có an toàn hơn Docker không?

Về thiết kế, có. Container rootless của Podman chạy dưới user thường, không phải root. Nếu container bị tấn công, phạm vi ảnh hưởng bị giới hạn. Docker chạy daemon với quyền root, nếu daemon bị lỗ hổng, rủi ro là toàn bộ host.

Tôi có thể chạy Podman trên VPS Windows Server không?

Podman có bản cho Windows nhưng hoạt động trong môi trường WSL2 hoặc máy ảo Linux. Trên Windows Server, Docker Desktop vẫn là lựa chọn phổ biến hơn. Nếu bạn cần container trên Windows, cân nhắc dùng VPS Windows với WSL2, còn nếu ưu tiên rootless container, dùng VPS Linux sẽ thuận tiện hơn nhiều.

Podman có hỗ trợ Kubernetes không?

Có. Lệnh podman play kube cho phép chạy file YAML của Kubernetes bằng Podman. Đây là cách chuyển từ Docker sang Kubernetes mà không cần thay đổi nhiều. Tuy nhiên, nếu bạn cần một cluster đầy đủ, hãy dùng k3s hoặc Kubernetes thật sự, không phải Podman.

Chạy Podman trên VPS có ngốn RAM không?

Ít hơn Docker vì không có daemon chạy nền. Mỗi container vẫn cần RAM riêng nhưng Podman không chiếm thêm bộ nhớ cho tiến trình quản lý. Với VPS 2GB RAM, bạn có thể chạy 3-4 container nhỏ như Nginx, Redis, Postgres mà không lo thiếu bộ nhớ. Nếu cần dung lượng lớn hơn, hãy xem các gói VPS giá rẻ với 4GB hoặc 8GB RAM.

Làm sao để cài Podman trên Ubuntu 20.04?

Ubuntu 20.04 đã hết hạn hỗ trợ chuẩn từ tháng 4 năm 2025. Bạn nên nâng cấp lên Ubuntu 24.04 LTS để có phiên bản Podman mới và nhận bản vá bảo mật. Podman trên Ubuntu 20.04 bản cũ có nhiều lỗi liên quan rootless container, không nên dùng cho production.

Bài viết liên quan

Lưu ý: Bài viết mang tính tham khảo, tổng hợp kiến thức chung. Mỗi hệ thống, hạ tầng và nhu cầu có đặc thù riêng, nên kiểm thử trong môi trường an toàn và tham vấn kỹ sư trước khi triển khai thực tế.