Virtualization

Quản lý container với Portainer trên VPS

Mở Terminal SSH vào VPS Linux mới cài Ubuntu 24.04, mình thấy đa số dev cứ mỗi lần muốn xem log container, restart container hay deploy bản mới là lại phải SSH vào server gõ lệnh docker. Làm riết mệt. Portainer là giải pháp thay thế: một giao diện web quản lý Docker, bạn vẫn có quyền root, vẫn chạy Docker Compose, nhưng click là xong. Bài này mình hướng dẫn cài Portainer lên VPS Ubuntu 24.04, cấu hình bảo mật cơ bản, và cách dùng các tính năng chính để quản lý container hàng ngày.

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

  • VPS chạy Ubuntu 24.04 (hoặc Debian 12, AlmaLinux 9) với quyền sudo.
  • Đã cài Docker và Docker Compose (nếu chưa, tham khảo bài cách cài Docker trên VPS Ubuntu).
  • Tên miền trỏ IP VPS (nếu muốn dùng HTTPS cho Portainer).
  • Bạn biết cơ bản về container: image, volume, network.

Vì sao nên dùng Portainer thay vì gõ lệnh Docker?

Khi bạn quản lý 1-2 container, gõ docker chẳng vấn đề. Nhưng khi có 5-10 container chạy song song: n8n + PostgreSQL + Redis, Nextcloud + MariaDB, Traefik, Uptime Kuma, rồi cả hàng chục stack khác, bạn không thể nhớ nổi cờ nào đã bật, volume nào dùng, container nào hay crash. Portainer hiển thị tất cả lên một dashboard: RAM, CPU, disk của từng container, log trực tiếp, restart/deploy bằng nút bấm. Mình đã chuyển sang Portainer từ ngày quản lý 10 container, tiết kiệm được cả giờ mỗi tuần.

Bước 1, Cài đặt Portainer Server với Docker Compose

Portainer có hai phiên bản: Portainer Server (giao diện quản lý) và Portainer Agent (chạy trên remote host nếu muốn quản lý nhiều VPS). Mình chỉ cần quản lý một VPS nên cài Portainer Server là đủ.

Tạo thư mục và file docker-compose:

sudo mkdir -p /opt/portainer
cd /opt/portainer
sudo nano docker-compose.yml

Nội dung:

version: '3.8'

services:
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    restart: unless-stopped
    ports:
      - "9000:9000"
      - "9443:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data

volumes:
  portainer_data:

Giải thích:

  • 9000:9000, cổng HTTP của Portainer.
  • 9443:9443, cổng HTTPS với chứng chỉ tự ký mặc định.
  • /var/run/docker.sock, mount socket Docker để Portainer giao tiếp với Docker daemon.
  • portainer_data, volume lưu cấu hình, dữ liệu.

Chạy stack:

sudo docker compose up -d

Verify:

sudo docker ps --filter "name=portainer"

Output mong đợi: container portainer đang Up.

Bước 2, Truy cập Portainer lần đầu và tạo admin

Mở trình duyệt: http://<IP_VPS>:9000 (hoặc https://<IP_VPS>:9443 nếu dùng HTTPS tự ký, trình duyệt sẽ cảnh báo, bỏ qua).

Màn hình đầu tiên yêu cầu tạo tài khoản admin:

  • Username: admin.
  • Password: đặt mật khẩu mạnh (12-16 ký tự, hoa thường số ký tự đặc biệt).

Sau đó chọn Get Started → chọn môi trường Local (quản lý Docker engine local) → Connect.

Lúc này bạn thấy dashboard tổng quan: số container đang chạy, số image, volume, network. Mất khoảng 1 phút là đã vào được.

Bước 3, Cấu hình bảo mật cho Portainer

Để Portainer lộ ra ngoài Internet ở cổng 9000 là không an toàn. Ít nhất bạn nên đặt sau Nginx reverse proxy với HTTPS Let's Encrypt, làm theo bài cấu hình Nginx reverse proxy cho n8n (áp dụng tương tự cho Portainer, chỉ khác port backend là 9000).

Nếu muốn cổng 9000 không mở ra ngoài, bạn có thể bind Portainer chỉ lên 127.0.0.1, rồi kết nối qua Nginx:

    ports:
      - "127.0.0.1:9000:9000"
      - "9443:9443"

Và thêm firewall chỉ mở cổng 80, 443 (hoặc 22) bằng ufw:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Kiểm tra: sudo ufw status verbose.

Ngoài ra, nếu không dùng HTTPS, bạn nên thay đổi mật khẩu admin thường xuyên và không đặt mật khẩu dễ đoán.

Bước 4, Các thao tác quản lý container cơ bản trên Portainer

Giám sát tài nguyên container

Vào Containers → chọn container muốn xem → tab Stats. Bạn thấy realtime CPU, RAM, network I/O. Cực kỳ hữu ích khi debug container chết vì OOM hay leak RAM, nhìn đồ thị là biết ngay.

Xem log container

Tại trang chi tiết container, tab Logs. Có thể lọc theo stdout/stderr, hoặc gõ keyword tìm lỗi. Ví dụ mình hay nhìn log của n8n để biết workflow nào lỗi.

Restart, stop, start, remove container

Trong danh sách container, mỗi container có nút Start, Stop, Restart, Remove (bên dưới nút toggle). Mất 1 giây click thay vì gõ docker restart.

Deploy stack từ docker-compose.yml

Vào Stacks+ Add stack → đặt tên → chọn Web editor và paste nội dung docker-compose.yml vào → Deploy the stack. Portainer tự pull image, tạo volume, network nếu cần. Nhanh hơn chạy lệnh nếu bạn thường xuyên deploy lại từ đầu môi trường dev.

Quản lý volumes và images

Tab Volumes: xem dung lượng, xóa volume không dùng. Tab Images: xem danh sách image, pull image mới, xóa image cũ để tiết kiệm disk.

Bước 5, Backup và restore Portainer

Portainer lưu toàn bộ dữ liệu trong volume portainer_data. Backup bằng lệnh:

sudo docker run --rm -v portainer_data:/data -v /backup:/backup alpine tar czf /backup/portainer-backup-$(date +%Y%m%d).tar.gz -C /data .

Restore:

sudo docker run --rm -v portainer_data:/data -v /backup:/backup alpine tar xzf /backup/portainer-backup-20260301.tar.gz -C /data

Mình thường đặt cron job chạy backup tự động hàng tuần. Nếu bạn dùng VPS NVMe có snapshot từ nhà cung cấp (như thueVPS cũng hỗ trợ), có thể kết hợp snapshot hàng ngày làm lớp bảo vệ thứ hai.

Bước 6, Giám sát Portainer và các container bằng Uptime Kuma

Mình dùng Uptime Kuma tự host để ping Portainer (cổng 9000 hoặc domain HTTPS) mỗi phút. Nếu Portainer chết, Uptime Kuma gửi cảnh báo Telegram. Ngoài ra, trong Portainer bạn có thể xem từng container có uptime bao lâu, ai đã restart, rất tiện khi debug sự cố đêm khuya.

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

Lỗi "Permission denied" khi mount docker.sock

Nguyên nhân: user chạy container portainer không có quyền đọc socket. Chạy lệnh kiểm tra:

ls -la /var/run/docker.sock
# output thường là srw-rw---- 1 root docker xxx

Nếu file socket thuộc group docker, bạn cần thêm user chạy Portainer vào group đó hoặc chạy Portainer với user root (image Portainer mặc định chạy root, nếu bạn không chỉnh user thì không lỗi). Cách fix: thêm dòng user: root trong service compose.

Không vào được Portainer do tường lửa

Chạy lệnh kiểm tra cổng đã mở:

ss -tlnp | grep 9000
sudo ufw status

Nếu chưa mở, thêm rule:

sudo ufw allow 9000/tcp

Portainer báo "Connection refused" khi truy cập

Thường do container Portainer chưa kịp khởi tạo. Đợi 10 giây và load lại. Hoặc kiểm tra log:

sudo docker logs portainer --tail 20

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

Portainer có miễn phí không?

Portainer Community Edition (CE) là mã nguồn mở hoàn toàn miễn phí. Bản Business Edition có thêm tính năng RBAC, quản lý Kubernetes, nếu bạn chỉ quản lý container Docker trên VPS thì bản CE là đủ.

Có cần cài Portainer Agent không?

Chỉ cần Portainer Agent khi bạn muốn quản lý nhiều Docker host từ một giao diện Portainer Server riêng biệt. Với một VPS, chỉ cần Portainer Server kết nối local Docker socket.

Portainer có ăn tài nguyên không?

Portainer Server chạy rất nhẹ. Mình chạy trên VPS 1 vCPU 2GB RAM thấy chiếm khoảng 50-70MB RAM và 1-2% CPU khi idle. Nếu không mở dashboard thường xuyên thì gần như không ảnh hưởng.

Làm sao update Portainer?

Dùng lệnh như update image Docker thông thường:

cd /opt/portainer
sudo docker compose pull
sudo docker compose up -d

Sau đó xóa image cũ nếu muốn: sudo docker image prune -a.

Portainer có hỗ trợ dark mode không?

Có. Vào Settings (icon bánh răng dưới dashboard) → chọn Dark theme, dễ nhìn hơn khi làm việc buổi tối.

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ế.