❤️ AZDIGI chính thức cập nhật hệ thống blog mới hoàn chỉnh. Tuy nhiên có thể một số bài viết bị sai lệch hình ảnh, hãy ấn nút Báo cáo bài viết ở cuối bài để AZDIGI cập nhật trong thời gian nhanh nhất. Chân thành cám ơn.

Bài 9, bạn đã học cách quản lý environment variables trong Docker một cách bài bản, từ file .env, cú pháp biến nâng cao, multi-environment setup cho đến Docker secrets. Cuối bài, mình có nhắc: tất cả vẫn chạy qua IP và port, chưa có domain, chưa có HTTPS.

Reverse Proxy với Nginx Proxy Manager
Minh họa: Reverse Proxy với Nginx Proxy Manager và SSL tự động

Bài này sẽ giải quyết đúng vấn đề đó. Bạn sẽ setup Nginx Proxy Manager : một reverse proxy có giao diện web, tích hợp SSL miễn phí , để mỗi container có domain riêng, HTTPS tự động, sẵn sàng cho production.

Vấn đề: Mỗi app một port

Khi chạy nhiều ứng dụng trên cùng một VPS bằng Docker, mỗi app sẽ expose một port khác nhau:

  • WordPress: http://your-ip:8080
  • Uptime Kuma: http://your-ip:3001
  • Portainer: http://your-ip:9443
  • n8n: http://your-ip:5678

Vấn đề rõ ràng nhận ra ngay:

  • Khó nhớ port: ai mà nhớ nổi 8080 là WordPress, 3001 là Uptime Kuma?
  • Không chuyên nghiệp: không lẽ sẽ sử dụng đường dẫn http://103.45.67.89:8080 gửi cho khách truy cập thì cũng kỳ
  • Không có HTTPS: trình duyệt hiện cảnh báo “Not Secure”, dữ liệu truyền không mã hoá
  • Phải mở nhiều port trên firewall: mỗi app một port, tăng rủi ro bảo mật

Giải pháp? Dùng reverse proxy.

Reverse Proxy là gì?

Hãy hình dung VPS của bạn như một toà nhà văn phòng. Mỗi container là một phòng ban (phòng kế toán, phòng nhân sự, phòng kỹ thuật). Nếu không có lễ tân, khách đến phải tự tìm phòng, chạy lên tầng 3, sang phòng 301, rồi lại xuống tầng 2…

Reverse proxy chính là lễ tân. Tất cả khách (request) đều đến lễ tân (cổng 80/443) trước. Lễ tân hỏi: “Bạn cần gặp ai?”, rồi dẫn khách đúng phòng ban.

Trong kỹ thuật: reverse proxy là một server đứng phía trước các ứng dụng, nhận tất cả request đến, kiểm tra domain/path, rồi chuyển tiếp (forward) đến đúng container phía sau.

Trước và sau khi có reverse proxy

Không có reverse proxy:

Client → http://103.45.67.89:8080  → WordPress container
Client → http://103.45.67.89:3001  → Uptime Kuma container
Client → http://103.45.67.89:5678  → n8n container

Có reverse proxy:

Client → https://blog.example.com    → Reverse Proxy → WordPress container
Client → https://status.example.com  → Reverse Proxy → Uptime Kuma container
Client → https://n8n.example.com     → Reverse Proxy → n8n container

Lợi ích của reverse proxy

  • Domain thay port: blog.example.com dễ nhớ hơn :8080
  • SSL tập trung: chỉ cần cài SSL ở reverse proxy, tất cả app phía sau đều có HTTPS
  • Bảo mật: các app không expose port ra internet, chỉ reverse proxy mới tiếp xúc bên ngoài
  • Load balancing: phân tải khi có nhiều instance của cùng một app
  • Firewall đơn giản: chỉ cần mở port 80 và 443

Nginx Proxy Manager – Reverse proxy cho người thích giao diện dễ dùng

Có nhiều reverse proxy phổ biến: Nginx, Traefik, Caddy, HAProxy… Mỗi cái đều mạnh, nhưng hầu hết yêu cầu bạn viết config file thủ công, dài dòng và dễ sai cú pháp.

Nginx Proxy Manager (NPM) giải quyết vấn đề đó bằng cách cung cấp một giao diện web để quản lý reverse proxy. Bạn không cần viết một dòng config Nginx nào, tất cả thao tác đều click trên trình duyệt.

Tại sao chọn Nginx Proxy Manager?

  • GUI web-based: thêm domain, cấu hình proxy, quản lý SSL bằng vài cú click
  • Tích hợp Let’s Encrypt: SSL miễn phí, tự động gia hạn, không cần chạy certbot thủ công
  • Access Lists: giới hạn truy cập cho các trang admin
  • Custom Nginx config: vẫn có thể thêm config Nginx tuỳ chỉnh khi cần
  • Chạy bằng Docker: deploy trong 2 phút, không ảnh hưởng hệ thống host

Nói ngắn gọn: NPM biến việc quản lý reverse proxy từ “sửa config file, reload nginx, debug lỗi cú pháp” thành “điền form, bấm Save”.

Deploy Nginx Proxy Manager bằng Docker Compose

Trước tiên, tạo thư mục project:

mkdir -p ~/docker/nginx-proxy-manager
cd ~/docker/nginx-proxy-manager

Tạo file docker-compose.yml:

version: "3.8"

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

networks: proxy-network: name: proxy-network driver: bridge

volumes: npm_data: npm_letsencrypt:

Giải thích cấu hình

  • Port 80: nhận traffic HTTP (sẽ redirect sang HTTPS)
  • Port 443: nhận traffic HTTPS
  • Port 81: giao diện admin của NPM: chỉ dùng để quản lý, sau khi setup xong có thể đóng port này trên firewall
  • npm_data: lưu database (SQLite mặc định), cấu hình proxy hosts
  • npm_letsencrypt: lưu SSL certificates từ Let’s Encrypt
  • proxy-network: network dùng chung giữa NPM và các container app: quan trọng nhất, đừng quên!

Khởi chạy:

docker compose up -d

Kiểm tra container đã chạy:

docker compose ps
NAME                    STATUS    PORTS
nginx-proxy-manager     Up        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:81->81/tcp

Tuỳ chọn: Dùng MariaDB thay SQLite

Mặc định NPM dùng SQLite, đủ tốt cho hầu hết trường hợp. Nếu bạn quản lý nhiều proxy hosts (50+) hoặc muốn dùng database riêng, có thể chuyển sang MariaDB:

version: "3.8"

services: npm: image: jc21/nginx-proxy-manager:latest container_name: nginx-proxy-manager restart: unless-stopped ports: - "80:80" - "443:443" - "81:81" environment: DB_MYSQL_HOST: npm-db DB_MYSQL_PORT: 3306 DB_MYSQL_USER: npm DB_MYSQL_PASSWORD: npm_password_change_me DB_MYSQL_NAME: npm volumes: - npm_data:/data - npm_letsencrypt:/etc/letsencrypt networks: - proxy-network depends_on: - npm-db

npm-db: image: mariadb:10.11 container_name: npm-db restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: root_password_change_me MYSQL_DATABASE: npm MYSQL_USER: npm MYSQL_PASSWORD: npm_password_change_me volumes: - npm_db_data:/var/lib/mysql networks: - proxy-network

networks: proxy-network: name: proxy-network driver: bridge

volumes: npm_data: npm_letsencrypt: npm_db_data:

Với hầu hết người dùng, SQLite là đủ. Bạn không cần MariaDB trừ khi có lý do cụ thể.

Setup ban đầu Nginx Proxy Manager

Trang đăng nhập Nginx Proxy Manager
Trang đăng nhập NPM tại port 81. Mặc định: admin@example.com / changeme

Sau khi container chạy, mở trình duyệt và truy cập:

http://your-vps-ip:81

Đăng nhập bằng tài khoản mặc định:

  • Email: admin@example.com
  • Password: changeme

Ngay khi đăng nhập lần đầu, NPM sẽ yêu cầu bạn:

  1. Đổi tên và email admin: nhập email thật của bạn
  2. Đổi password: chọn password mạnh, đây là tài khoản quản trị reverse proxy

Sau khi đổi password, bạn sẽ thấy dashboard chính của NPM, hiện tại còn trống vì chưa cấu hình gì. Mình sẽ thêm proxy hosts ở phần tiếp theo.

Dashboard Nginx Proxy Manager
Dashboard NPM sau khi đăng nhập. Hiển thị số lượng Proxy Hosts, Redirection Hosts, Streams, 404 Hosts.

Deploy ứng dụng mẫu

Để demo reverse proxy, mình sẽ deploy 2 ứng dụng: WordPressUptime Kuma. Cả hai đều chạy trên cùng Docker network với NPM, đây là điều kiện bắt buộc để NPM forward request được.

App 1: WordPress

Tạo thư mục và file compose cho WordPress:

mkdir -p ~/docker/wordpress
cd ~/docker/wordpress

Tạo file docker-compose.yml:

version: "3.8"

services: wordpress: image: wordpress:latest container_name: wordpress-app restart: unless-stopped environment: WORDPRESS_DB_HOST: wordpress-db WORDPRESS_DB_USER: wp_user WORDPRESS_DB_PASSWORD: wp_password_change_me WORDPRESS_DB_NAME: wordpress volumes: - wp_data:/var/www/html networks: - proxy-network

wordpress-db: image: mariadb:10.11 container_name: wordpress-db restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: root_password_change_me MYSQL_DATABASE: wordpress MYSQL_USER: wp_user MYSQL_PASSWORD: wp_password_change_me volumes: - wp_db_data:/var/lib/mysql networks: - proxy-network

networks: proxy-network: external: true

volumes: wp_data: wp_db_data:

Lưu ý quan trọng:

  • Không có phần ports: cho WordPress: container không expose port nào ra ngoài. Chỉ có NPM mới truy cập được qua Docker network.
  • proxy-networkexternal: true: vì network này đã được tạo bởi NPM compose file ở trên. Tất cả app muốn dùng reverse proxy đều phải join network này.
docker compose up -d

App 2: Uptime Kuma

Uptime Kuma là công cụ monitoring uptime, giao diện đẹp, nhẹ, rất phổ biến trong cộng đồng self-hosted.

mkdir -p ~/docker/uptime-kuma
cd ~/docker/uptime-kuma

Tạo file docker-compose.yml:

version: "3.8"

services: uptime-kuma: image: louislam/uptime-kuma:latest container_name: uptime-kuma restart: unless-stopped volumes: - kuma_data:/app/data networks: - proxy-network

networks: proxy-network: external: true

volumes: kuma_data:

Tương tự WordPress, không expose port, chỉ join proxy-network.

docker compose up -d

Kiểm tra tất cả container đang chạy:

docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
NAMES                   STATUS    PORTS
nginx-proxy-manager     Up        0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:81->81/tcp
wordpress-app           Up        80/tcp
wordpress-db            Up        3306/tcp
uptime-kuma             Up        3001/tcp

Để ý: WordPress và Uptime Kuma có port nhưng không có 0.0.0.0: phía trước, nghĩa là port chỉ mở bên trong Docker network, không expose ra internet. Đúng như mong muốn!

Trỏ domain về VPS

Trước khi cấu hình proxy host trong NPM, bạn cần trỏ domain về IP của VPS.

Với domain thật

Vào phần quản lý DNS của domain (Cloudflare, Route53, hoặc nhà đăng ký domain), tạo A record:

blog.example.com      A    103.45.67.89
status.example.com    A    103.45.67.89

Nếu dùng Cloudflare, tắt proxy (cloud icon màu cam) trong lúc setup để Let’s Encrypt có thể verify domain. Sau khi SSL hoạt động, bạn có thể bật lại.

Test không có domain? Dùng /etc/hosts

Nếu bạn chưa có domain hoặc chỉ muốn test local, sửa file /etc/hosts trên máy tính của bạn (không phải VPS):

Trên macOS/Linux:

sudo nano /etc/hosts

Trên Windows: mở Notepad as Administrator, mở file C:\Windows\System32\drivers\etc\hosts

Thêm dòng:

103.45.67.89    blog.example.com
103.45.67.89    status.example.com

Thay 103.45.67.89 bằng IP VPS của bạn. Sau đó bạn có thể truy cập blog.example.com từ trình duyệt, trình duyệt sẽ gửi request đến IP VPS thay vì tìm DNS trên internet.

Lưu ý: Với cách này, bạn sẽ không thể cài SSL bằng Let’s Encrypt vì Let’s Encrypt cần verify domain qua internet. Tuy nhiên, bạn vẫn có thể test proxy host mà không cần SSL.

Cấu hình Proxy Host trong NPM

Danh sách Proxy Hosts trên NPM
Tab Proxy Hosts, nơi quản lý tất cả reverse proxy rules.

Đây là phần chính, kết nối domain với container thông qua NPM.

Thêm Proxy Host cho WordPress

Form thêm Proxy Host mới trên NPM
Thêm Proxy Host: nhập domain, forward hostname (tên container), port. NPM tự route traffic.

Trong giao diện NPM (http://your-vps-ip:81), vào Hosts → Proxy Hosts → Add Proxy Host.

Tab Details:

  • Domain Names: blog.example.com
  • Scheme: http
  • Forward Hostname / IP: wordpress-app (tên container)
  • Forward Port: 80 (port bên trong container WordPress)
  • Block Common Exploits: ✅ bật
  • Websockets Support: không cần cho WordPress

Tại sao dùng container name thay vì IP? Vì NPM và WordPress cùng network proxy-network, Docker DNS tự động resolve wordpress-app thành IP nội bộ của container. Không cần biết IP cụ thể là bao nhiêu.

Tab SSL (nếu có domain thật trỏ về VPS):

  • SSL Certificate: chọn Request a new SSL Certificate
  • Force SSL: ✅ bật: tự động redirect HTTP → HTTPS
  • HTTP/2 Support: ✅ bật
  • HSTS Enabled: ✅ bật (tuỳ chọn, bật nếu bạn chắc chắn luôn dùng HTTPS)
  • Email Address for Let’s Encrypt: nhập email thật của bạn
  • I Agree to the Let’s Encrypt ToS: ✅ đồng ý

Bấm Save. NPM sẽ tự động:

  1. Tạo cấu hình Nginx cho domain blog.example.com
  2. Request SSL certificate từ Let’s Encrypt
  3. Cấu hình auto-renew (tự động gia hạn trước khi hết hạn)

Truy cập https://blog.example.com: bạn sẽ thấy trang cài đặt WordPress. HTTPS, ổ khoá xanh, đầy đủ!

Proxy Host đã tạo thành công
Proxy Host cho WordPress đã active, sẵn sàng nhận traffic.

Thêm Proxy Host cho Uptime Kuma

Tương tự, thêm proxy host mới:

Tab Details:

  • Domain Names: status.example.com
  • Scheme: http
  • Forward Hostname / IP: uptime-kuma
  • Forward Port: 3001
  • Block Common Exploits:
  • Websockets Support: ✅ bật: Uptime Kuma dùng WebSocket cho real-time updates

Tab SSL: cấu hình giống WordPress, Request new SSL, Force SSL, HTTP/2.

Save xong, truy cập https://status.example.com: Uptime Kuma hiện ra với HTTPS.

Cách hoạt động đằng sau

Để hiểu rõ hơn, hãy xem flow từ khi người dùng gõ URL đến khi nhận được trang web:

1. Người dùng gõ: https://blog.example.com
2. DNS resolve: blog.example.com → 103.45.67.89 (IP VPS)
3. Trình duyệt kết nối đến 103.45.67.89:443 (HTTPS)
4. NPM nhận request, đọc header "Host: blog.example.com"
5. NPM tìm proxy host match domain → forward đến wordpress-app:80
6. WordPress xử lý request, trả response cho NPM
7. NPM trả response lại cho trình duyệt

SSL Termination

Một khái niệm quan trọng: SSL termination. Khi NPM nhận kết nối HTTPS từ client, nó giải mã SSL tại đây, rồi forward request dưới dạng HTTP thông thường đến container phía sau.

Client ←→ [HTTPS] ←→ NPM ←→ [HTTP] ←→ WordPress container

Điều này có nghĩa:

  • Container app không cần cài SSL: NPM lo hết
  • Traffic giữa NPM và container là HTTP: nhưng vì cùng Docker network (không đi qua internet), điều này an toàn
  • Nếu cần end-to-end encryption, bạn có thể đổi Scheme thành https trong proxy host: nhưng hiếm khi cần thiết

Docker Network – Sợi dây kết nối

Lý do mọi thứ hoạt động là nhờ Docker network. Khi NPM và các app cùng join proxy-network:

  • Docker tạo một mạng nội bộ riêng
  • Mỗi container có thể gọi nhau bằng container name (Docker DNS tự resolve)
  • NPM gọi wordpress-app:80 → Docker DNS trả về IP nội bộ của container WordPress

Nếu bạn quên join proxy-network, NPM sẽ không thể kết nối đến container, bạn sẽ thấy lỗi 502 Bad Gateway.

Tips & Best Practices

1. Không expose port app ra ngoài

Đây là best practice quan trọng nhất. Khi dùng reverse proxy, chỉ NPM mới expose port 80/443 ra internet. Các app phía sau không cần (và không nên) expose port.

# ❌ Sai — expose port ra ngoài
services:
  wordpress:
    ports:
      - "8080:80"    # Ai cũng truy cập được qua :8080
# ✅ Đúng — không expose port
services:
  wordpress:
    # Không có phần ports:
    networks:
      - proxy-network    # Chỉ truy cập qua NPM

Nếu bạn cần truy cập trực tiếp container để debug, dùng:

# Truy cập container trực tiếp qua Docker network
docker exec -it wordpress-app bash
# Hoặc expose port tạm thời chỉ trên localhost
ports:
  - "127.0.0.1:8080:80"    # Chỉ truy cập từ VPS, không từ internet

2. Access List cho admin panels

Một số trang (như admin panel của NPM, Portainer, phpMyAdmin) không nên public. NPM có tính năng Access Lists để giới hạn truy cập:

Trong NPM, vào Access Lists → Add Access List:

  • Name: Admin Only
  • Satisfy Any: chọn tuỳ nhu cầu
  • Tab Authorization: thêm username/password
  • Tab Access: cho phép IP cụ thể (ví dụ: allow 1.2.3.4: IP nhà bạn)

Sau đó, khi tạo proxy host cho admin panel, chọn Access List là Admin Only. Ai không có password hoặc không từ IP cho phép sẽ bị chặn.

3. Custom Nginx config

NPM cho phép thêm custom Nginx config cho từng proxy host. Khi tạo/sửa proxy host, vào tab Advanced và thêm config:

# Tăng giới hạn upload file (mặc định Nginx chỉ cho 1MB)
client_max_body_size 100M;

# Custom headers proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# Cache static files location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; add_header Cache-Control "public, immutable"; }

Đặc biệt với WordPress, bạn gần như chắc chắn cần tăng client_max_body_size vì WordPress hay upload media lớn.

4. Wildcard SSL Certificate

Nếu bạn có nhiều subdomain (blog.example.com, status.example.com, api.example.com…), thay vì tạo SSL riêng cho từng cái, dùng wildcard certificate: *.example.com.

Trong NPM, vào SSL Certificates → Add SSL Certificate → Let’s Encrypt:

  • Domain Names: *.example.comexample.com
  • Use a DNS Challenge: ✅ bật: bắt buộc cho wildcard
  • DNS Provider: chọn provider (Cloudflare, DigitalOcean, Route53…)
  • Credentials File Content: nhập API key/token của DNS provider

Ví dụ với Cloudflare:

dns_cloudflare_api_token = your_cloudflare_api_token_here

Sau khi tạo wildcard cert, bạn có thể chọn cert này khi tạo proxy host thay vì request cert mới mỗi lần.

5. Bảo vệ admin panel NPM

Port 81 (admin panel NPM) mặc định mở cho tất cả. Sau khi setup xong, bạn nên bảo vệ nó:

Cách 1: Chặn port 81 trên firewall, chỉ truy cập qua SSH tunnel:

# Trên VPS — chặn port 81 từ bên ngoài
sudo ufw deny 81

# Trên máy local — tạo SSH tunnel ssh -L 8181:localhost:81 user@your-vps-ip

# Mở trình duyệt: http://localhost:8181

Cách 2: Tạo proxy host cho NPM admin luôn (ví dụ: npm.example.com), thêm Access List, rồi đóng port 81:

# Sửa docker-compose.yml của NPM, bỏ port 81 ra ngoài
ports:
  - "80:80"
  - "443:443"
  # - "81:81"    # Không expose nữa, truy cập qua proxy host

Thêm app mới – Quy trình chuẩn

Sau khi setup NPM xong, mỗi khi deploy app mới, bạn chỉ cần 3 bước:

  1. Deploy app: compose file với proxy-network, không expose port
  2. Trỏ DNS: tạo A record cho subdomain mới
  3. Thêm Proxy Host trong NPM: domain → container name + port → SSL

3 bước, 5 phút. Mỗi app mới đều có domain riêng, HTTPS tự động, không cần sửa config Nginx thủ công.

Troubleshooting thường gặp

502 Bad Gateway

Nguyên nhân phổ biến nhất: NPM không kết nối được đến container app.

  • Kiểm tra container app đang chạy: docker ps
  • Kiểm tra cùng network: docker network inspect proxy-network
  • Kiểm tra forward port đúng (port bên trong container, không phải port expose)
  • Kiểm tra container name đúng chính tả

SSL certificate lỗi

  • Domain chưa trỏ về IP VPS: kiểm tra bằng dig blog.example.com hoặc nslookup blog.example.com
  • Port 80 bị chặn trên firewall: Let’s Encrypt cần port 80 để verify
  • Cloudflare proxy đang bật (cloud màu cam): tắt khi request cert
  • Đã request quá nhiều cert: Let’s Encrypt có rate limit (50 cert/domain/tuần)

Redirect loop (ERR_TOO_MANY_REDIRECTS)

Thường xảy ra khi dùng Cloudflare proxy + NPM Force SSL. Cloudflare và NPM đều cố redirect HTTP → HTTPS → loop vô hạn.

Giải pháp: trong Cloudflare, đặt SSL mode là Full hoặc Full (Strict), không dùng Flexible.

📚 Serie Docker từ A đến Z

  1. Bài 1: Docker là gì? Tại sao nên dùng Docker trên VPS
  2. Bài 2: Cài đặt Docker và Docker Compose trên VPS Ubuntu
  3. Bài 3: Làm quen với Docker – Các lệnh cơ bản cần biết
  4. Bài 4: Docker Image & Dockerfile – Tự tạo Image riêng
  5. Bài 5: Docker Volume & Network – Quản lý dữ liệu và mạng
  6. Bài 6: Docker Compose là gì? Cài đặt và cú pháp cơ bản
  7. Bài 7: Deploy WordPress + MySQL + phpMyAdmin bằng Docker Compose
  8. Bài 8: Deploy LEMP Stack (Nginx + PHP-FPM + MariaDB) bằng Docker Compose
  9. Bài 9: Biến môi trường & file .env trong Docker Compose
  10. Bài 10: Reverse Proxy với Nginx Proxy Manager + SSL tự động (đang đọc)
  11. Bài 11: Deploy ứng dụng Node.js / Python với Docker Compose
  12. Bài 12: Backup & Restore dữ liệu Docker Volume
  13. Bài 13: Monitoring Docker với Portainer, Uptime Kuma và cAdvisor
  14. Bài 14: Docker Logging – Quản lý log hiệu quả
  15. Bài 15: Bảo mật Docker trên VPS
  16. Bài 16: CI/CD đơn giản – Auto deploy với Webhook + Docker Compose
  17. Bài 17: Docker Compose trong thực tế – Tổng hợp project mẫu

Tổng kết

Qua bài này, bạn đã:

  • Hiểu reverse proxy là gì và tại sao cần nó khi chạy nhiều app trên 1 VPS
  • Deploy Nginx Proxy Manager bằng Docker Compose
  • Deploy các app mẫu (WordPress, Uptime Kuma) không expose port, chỉ truy cập qua reverse proxy
  • Cấu hình proxy host + SSL tự động từ Let’s Encrypt
  • Hiểu cách hoạt động: DNS → NPM → Docker network → Container
  • Best practices: không expose port, Access List, custom Nginx config, wildcard SSL

Đến đây, bạn đã có một VPS chạy Docker khá “pro” rồi: build image, compose, volumes, networks, env vars, và giờ là reverse proxy + SSL. Tất cả container đều có domain riêng, HTTPS tự động, sẵn sàng cho production.

Nhưng Docker không chỉ để chạy WordPress hay các tool có sẵn. Trong Bài 11, mình sẽ hướng dẫn bạn deploy ứng dụng Node.js và Python bằng Docker, viết Dockerfile cho app của chính bạn, tối ưu image size, kết hợp với Nginx Proxy Manager để serve app lên production. Hẹn gặp bạn ở bài tiếp theo! 🚀

👈 Bài trước: Biến môi trường & file .env trong Docker Compose

👉 Bài tiếp: Deploy ứng dụng Node.js / Python với Docker Compose

Chia sẻ:
Bài viết đã được kiểm duyệt bởi AZDIGI Team

Về tác giả

Thạch Phạm

Thạch Phạm

Đồng sáng lập và Giám đốc điều hành của AZDIGI. Có hơn 15 năm kinh nghiệm trong phổ biến kiến thức liên quan đến WordPress tại thachpham.com, phát triển website và phát triển hệ thống.

Hơn 10 năm phục vụ 80.000+ khách hàng

Bắt đầu dự án web của bạn với AZDIGI