Triển khai WordPress bằng Portainer: Nginx MySQL SSL A-Z

P P T P Chung

Triển khai WordPress bằng Portainer: Nginx, MySQL, SSL đầy đủ

Bạn có VPS. Muốn chạy WordPress ổn định. Không muốn gõ Docker dài. Không muốn sửa Nginx thủ công mỗi lần thêm site. Portainer → quản trị Docker bằng UI. Nginx Proxy Manager → reverse proxy + SSL Let’s Encrypt. MySQL → DB riêng. WordPress → chạy trong container, dễ backup, dễ nâng cấp.

Mô hình này phù hợp blog cá nhân, landing page, site doanh nghiệp nhỏ/vừa. Ưu điểm: tách dịch vụ, dễ di chuyển, dễ rollback, SSL tự động, không đụng quá sâu vào host.


Kiến trúc triển khai

Mô hình:

Portainer → quản lý Docker qua web. – Nginx Proxy Manager → nhận HTTP/HTTPS từ internet. – WordPress container → chạy PHP/Apache nội bộ. – MySQL container → lưu DB. – Docker network → các container giao tiếp riêng. – Volumes → giữ dữ liệu bền vững.

Luồng req:

User → domain.com → Nginx Proxy Manager → WordPress → MySQL

Cổng public cần mở:

80 → HTTP, cấp SSL. – 443 → HTTPS. – 9443 → Portainer, nên giới hạn IP nếu có thể. – 81 → Nginx Proxy Manager UI, nên chặn public sau cấu hình.


Chuẩn bị VPS

Yêu cầu tối thiểu:

– Ubuntu 22.04/24.04. – RAM 1GB chạy được, 2GB+ khuyến nghị. – Docker + Docker Compose plugin. – Domain trỏ A record về IP VPS.

Cài Docker nhanh:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER

Đăng xuất/đăng nhập lại. Kiểm tra:

docker version
docker compose version

Tạo thư mục dự án:

mkdir -p ~/stacks/wordpress
cd ~/stacks/wordpress

Cài Portainer

Portainer giúp tạo stack, xem logs, restart container, chỉnh env, quản lý volumes.

Chạy:

docker volume create portainer_data

docker run -d --name portainer --restart=always -p 9443:9443 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest

Mở:

https://YOUR_SERVER_IP:9443

Tạo admin user. Chọn Docker local environment.

Lưu ý bảo mật:

– Dùng password mạnh. – Không public Portainer nếu không cần. – Nên firewall giới hạn IP truy cập 9443.


Tạo Docker network chung

Network chung giúp Nginx Proxy Manager nhìn thấy WordPress container.

Trong terminal:

docker network create proxy

Nếu làm trong Portainer: Networks → Add network → name: proxy → bridge.

Network này dùng cho:

– Nginx Proxy Manager. – WordPress app.

MySQL có thể nằm cùng network riêng của stack. Nhưng để đơn giản, dùng chung stack network + proxy cho WordPress.


Triển khai Nginx Proxy Manager

Tạo stack trong Portainer: Stacks → Add stack → name: npm.

Dán:

services:
  npm:
    image: jc21/nginx-proxy-manager:latest
    container_name: npm
    restart: unless-stopped
    ports:
      - "80:80"
      - "81:81"
      - "443:443"
    volumes:
      - npm_data:/data
      - npm_letsencrypt:/etc/letsencrypt
    networks:
      - proxy

volumes: npm_data: npm_letsencrypt:

networks: proxy: external: true

Deploy. Mở:

http://YOUR_SERVER_IP:81

Login mặc định:

Email: [email protected]
Password: changeme

Đổi ngay email/password.

Cảnh báo: cổng 81 là dashboard quản trị. Sau khi cấu hình xong, nên firewall giới hạn IP hoặc không expose public nếu dùng VPN/tunnel.


Triển khai WordPress + MySQL

Tạo stack mới: Stacks → Add stack → name: wordpress-site1.

Dùng Compose:

services:
  db:
    image: mysql:8.0
    container_name: wp_db_site1
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: change_this_strong_password
      MYSQL_ROOT_PASSWORD: change_this_root_password
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - internal

wordpress: image: wordpress:latest container_name: wp_app_site1 restart: unless-stopped depends_on: - db environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_NAME: wordpress WORDPRESS_DB_USER: wpuser WORDPRESS_DB_PASSWORD: change_this_strong_password volumes: - wp_data:/var/www/html networks: - internal - proxy

volumes: db_data: wp_data:

networks: internal: proxy: external: true

Trước deploy, đổi password. Không dùng password mẫu.

Deploy stack. Kiểm tra logs:

– Portainer → Containers → wp_app_site1 → Logs. – Không lỗi DB connection → ổn.

WordPress chưa public trực tiếp vì không map port. Đúng. Nginx Proxy Manager sẽ route nội bộ.


Trỏ domain

Trong DNS provider:

A    @      YOUR_SERVER_IP
A    www    YOUR_SERVER_IP

Chờ DNS propagate. Kiểm tra:

dig domain.com +short
dig www.domain.com +short

Kết quả phải là IP VPS.


Cấu hình Nginx Proxy Manager

Vào NPM:

Hosts → Proxy Hosts → Add Proxy Host

Tab Details:

– Domain Names: domain.com, www.domain.com – Scheme: http – Forward Hostname/IP: wp_app_site1 – Forward Port: 80 – Cache Assets: bật tùy chọn – Block Common Exploits: bật – Websockets Support: thường không cần, bật cũng được

Tab SSL:

– Request a new SSL Certificate – Email: email thật – Agree Let’s Encrypt Terms – Force SSL: bật – HTTP/2 Support: bật – HSTS: chỉ bật khi chắc chắn site luôn HTTPS

Save.

Nếu thành công: truy cập https://domain.com → màn hình cài WordPress.

Nếu lỗi SSL:

– DNS chưa trỏ đúng. – Port 80/443 bị firewall/cloud firewall chặn. – Domain đang bật proxy/CDN sai mode. – Container NPM không chạy.


Cài WordPress ban đầu

Mở:

https://domain.com

Chọn:

– Ngôn ngữ. – Site title. – Admin username. – Password mạnh. – Email admin.

Không dùng username admin. Sau cài đặt:

– Settings → Permalinks → chọn Post name. – Settings → General → kiểm tra URL là https://domain.com. – Cài plugin cần thiết vừa đủ.

Nếu WordPress nhận sai HTTPS, thêm vào wp-config.php. Với Docker volume, có thể exec:

docker exec -it wp_app_site1 bash

Sửa:

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

Thường image WordPress + NPM xử lý ổn. Chỉ sửa khi bị redirect loop hoặc mixed scheme.


Tối ưu cấu hình thực tế

Upload size

Mặc định có thể thấp. Tạo file custom PHP config.

Cách nhanh: mount thêm file uploads.ini.

Tạo thư mục:

mkdir -p ~/stacks/wordpress/php
nano ~/stacks/wordpress/php/uploads.ini

Nội dung:

file_uploads = On
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 300

Sửa service WordPress:

volumes:
      - wp_data:/var/www/html
      - ./php/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini

Redeploy stack.

Bộ nhớ

VPS RAM thấp → thêm swap:

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Swap không thay RAM thật, nhưng giúp tránh MySQL chết khi spike.

Cache

Nên dùng:

– Plugin cache: LiteSpeed Cache không tối ưu nếu không dùng LiteSpeed; dùng WP Super Cache, W3 Total Cache, hoặc Cache Enabler. – Object cache: Redis nếu site lớn. – CDN: Cloudflare cho static assets.

Với Nginx Proxy Manager, có thể bật Cache Assets, nhưng cache app-level vẫn cần plugin.


Backup đúng cách

Dữ liệu quan trọng gồm:

wp_data → code, themes, plugins, uploads. – db_data → MySQL data. – DB dump → an toàn hơn backup raw volume.

Backup DB:

docker exec wp_db_site1 mysqldump 
  -u root 
  -pchange_this_root_password 
  wordpress > wordpress.sql

Backup volume:

docker run --rm 
  -v wordpress-site1_wp_data:/data 
  -v $(pwd):/backup 
  alpine tar czf /backup/wp_data.tar.gz -C /data .

Khuyến nghị:

– Backup hằng ngày DB. – Backup uploads hằng ngày/tuần tùy tần suất. – Đẩy backup ra ngoài VPS: S3, Backblaze B2, Google Drive, rsync server. – Test restore định kỳ. Backup chưa test → chưa chắc dùng được.


Nâng cấp container an toàn

WordPress app có 2 lớp:

– WordPress core/plugin/theme trong volume. – Container image PHP/Apache.

Cách nâng cấp image:

1. Backup DB + files. 2. Trong Portainer → Stack → Pull latest image/redeploy. 3. Kiểm tra logs. 4. Mở site, test login, post, upload.

MySQL major upgrade cần cẩn trọng. Không nhảy tùy tiện từ 5.7 → 8.0 hoặc 8.0 → 8.4 nếu chưa đọc migration note. Với site production, pin version:

image: mysql:8.0

Không dùng latest cho DB production.


Bảo mật cần làm

– Admin WordPress: password mạnh + 2FA. – Portainer/NPM UI: giới hạn IP bằng firewall. – VPS: chỉ mở port cần thiết. – SSH: key-based login, tắt password login nếu quen vận hành. – WordPress: xóa theme/plugin không dùng. – Cập nhật plugin đều. – Không cấp quyền ghi lung tung trên host. – Không đưa DB port ra public. – Không commit password vào repo public.

UFW mẫu:

sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw allow from YOUR_IP to any port 9443
sudo ufw allow from YOUR_IP to any port 81
sudo ufw enable

Lỗi thường gặp

Error establishing a database connection

Nguyên nhân:

– Sai WORDPRESS_DB_PASSWORD. – DB chưa ready. – Sai hostname DB.

Fix:

WORDPRESS_DB_HOST: db:3306 – Kiểm tra logs MySQL. – Không đổi env DB sau khi volume đã tạo mà không hiểu tác động.

502 Bad Gateway

Nguyên nhân:

– NPM không thấy WordPress container. – Sai Forward Hostname. – WordPress chưa chạy.

Fix:

– WordPress phải join network proxy. – Forward Hostname dùng wp_app_site1. – Check logs.

SSL không cấp được

Nguyên nhân:

– DNS sai. – Port 80 bị chặn. – AAAA record trỏ sai IPv6. – Cloudflare SSL mode gây lỗi.

Fix:

– Xóa AAAA nếu không dùng IPv6. – Mở port 80/443. – Tạm tắt proxy Cloudflare khi cấp cert.


Kết luận

Portainer + Nginx Proxy Manager + MySQL + WordPress là combo gọn, dễ vận hành, đủ mạnh cho nhiều website production nhỏ/vừa. Portainer giúp quản trị trực quan. NPM xử lý reverse proxy + SSL sạch. Docker volumes giữ dữ liệu độc lập. Compose stack giúp tái tạo nhanh.

Điểm mấu chốt: không expose DB, backup đều, giới hạn UI quản trị, pin version DB, kiểm tra logs khi lỗi. Làm đúng từ đầu → triển khai WordPress mới chỉ mất vài phút, thêm domain mới cũng rất nhanh.

Tác giả

P T P

Chia sẻ

Bài viết liên quan

Bình luận (0)

Email của bạn sẽ không được hiển thị công khai.

Chưa có bình luận. Hãy là người đầu tiên!