Docker + Nginx Proxy Manager 在香港VPS管理多站点:一键HTTPS与容器编排实战
在单台香港 VPS 上同时运行多个网站,传统做法是手动维护大量 Nginx 配置文件,每次添加站点、申请证书都要重复操作。Nginx Proxy Manager(NPM) 提供了一个可视化 Web 界面,结合 Docker 容器化,让多站点管理变得像填表格一样简单,同时实现完整的容器级隔离。
一、架构设计
<code">
外部请求(80/443)
│
┌─────▼──────────────────────────────────────┐
│ Nginx Proxy Manager(反向代理层) │
│ Web UI 管理 · 自动 Let's Encrypt 证书 │
└──┬────────────────┬────────────────┬────────┘
│ │ │
┌────▼────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ WordPress│ │ Ghost Blog │ │ Nextcloud │
│ :8001 │ │ :8002 │ │ :8003 │
└──────────┘ └─────────────┘ └─────────────┘
Docker 网络隔离,各容器独立运行
二、安装 Docker 与 Docker Compose
<code"># 一键安装 Docker curl -fsSL https://get.docker.com | sh systemctl enable --now docker # 验证 docker --version docker compose version
三、部署 Nginx Proxy Manager
<code">mkdir -p /opt/npm && cd /opt/npm
cat > docker-compose.yml << 'EOF'
version: '3.8'
networks:
proxy-net:
driver: bridge
name: proxy-net # 全局网络,所有站点容器加入此网络
services:
nginx-proxy-manager:
image: jc21/nginx-proxy-manager:latest
container_name: npm
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "81:81" # NPM Web 管理界面端口
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
networks:
- proxy-net
# NPM 内置数据库
db:
image: jc21/mariadb-aria:latest
container_name: npm-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: npm_root_pass
MYSQL_DATABASE: npm
MYSQL_USER: npm
MYSQL_PASSWORD: npm_pass
volumes:
- ./mysql:/var/lib/mysql
networks:
- proxy-net
EOF
docker compose up -d访问 http://你的服务器IP:81,默认账号:admin@example.com / changeme,首次登录后立即修改密码。
四、部署多个站点容器
站点一:WordPress
<code">mkdir -p /opt/sites/wordpress && cd /opt/sites/wordpress
cat > docker-compose.yml << 'EOF'
version: '3.8'
networks:
proxy-net:
external: true # 接入 NPM 共享网络
services:
wordpress:
image: wordpress:php8.1-fpm
container_name: wp-site1
restart: unless-stopped
environment:
WORDPRESS_DB_HOST: wp-mysql
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: wp_pass
WORDPRESS_TABLE_PREFIX: wp_
volumes:
- ./wp-content:/var/www/html/wp-content
networks:
- proxy-net
expose:
- "9000" # 只在内网暴露,不对外开放
wp-mysql:
image: mysql:8.0
container_name: wp-mysql
restart: unless-stopped
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wp_user
MYSQL_PASSWORD: wp_pass
MYSQL_ROOT_PASSWORD: root_pass
volumes:
- ./mysql-data:/var/lib/mysql
networks:
- proxy-net
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M # 资源限制,防止单站点耗尽服务器资源
EOF
docker compose up -d站点二:Ghost 博客
<code">mkdir -p /opt/sites/ghost && cd /opt/sites/ghost
cat > docker-compose.yml << 'EOF'
version: '3.8'
networks:
proxy-net:
external: true
services:
ghost:
image: ghost:5-alpine
container_name: ghost-blog
restart: unless-stopped
environment:
url: https://blog.yourdomain.com
database__client: mysql
database__connection__host: ghost-mysql
database__connection__database: ghost
database__connection__user: ghost_user
database__connection__password: ghost_pass
mail__transport: SMTP
mail__options__host: smtp.yourdomain.com
volumes:
- ./ghost-content:/var/lib/ghost/content
networks:
- proxy-net
expose:
- "2368"
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
ghost-mysql:
image: mysql:8.0
container_name: ghost-mysql
environment:
MYSQL_DATABASE: ghost
MYSQL_USER: ghost_user
MYSQL_PASSWORD: ghost_pass
MYSQL_ROOT_PASSWORD: root_pass
volumes:
- ./mysql-data:/var/lib/mysql
networks:
- proxy-net
EOF
docker compose up -d五、在 Nginx Proxy Manager 中配置反向代理
进入 NPM Web 界面(http://IP:81),按以下步骤添加站点:
- 点击 Proxy Hosts → Add Proxy Host
- 填写:
- Domain Names:
site1.yourdomain.com - Forward Hostname / IP:
wp-site1(容器名,NPM 通过 Docker 网络直接解析) - Forward Port:
80 - 勾选 Block Common Exploits(基础安全防护)
- Domain Names:
- 切换到 SSL 标签:
- 选择 Request a new SSL Certificate
- 勾选 Force SSL 和 HTTP/2 Support
- 填写邮箱,点击 Save
NPM 会自动向 Let’s Encrypt 申请证书并配置 HTTPS,全程约 30 秒,无需命令行操作。
六、容器资源管理与监控
<code"># 查看所有站点容器资源占用 docker stats --no-stream # 输出示例: # CONTAINER CPU % MEM USAGE / LIMIT NET I/O # npm 0.2% 45MiB / 8GiB ... # wp-site1 0.8% 128MiB / 512MiB ... # ghost-blog 0.3% 89MiB / 256MiB ... # wp-mysql 0.5% 210MiB / 512MiB ...
<code"># 查看某个容器的实时日志 docker logs -f wp-site1 --tail 50 # 进入容器调试 docker exec -it wp-site1 bash # 重启单个站点(不影响其他站点) docker restart ghost-blog
七、统一备份脚本(所有站点数据卷)
<code">cat > /usr/local/bin/backup-docker-sites.sh << 'SCRIPT' #!/bin/bash DATE=$(date +%Y%m%d) BACKUP_DIR="/backup/docker-sites/$DATE" mkdir -p $BACKUP_DIR # 备份各站点数据卷 for site in wordpress ghost; do docker run --rm \ -v /opt/sites/$site:/source:ro \ -v $BACKUP_DIR:/backup \ alpine \ tar -czf /backup/${site}-${DATE}.tar.gz -C /source . echo "已备份: $site" done # 清理 7 天前备份 find /backup/docker-sites -maxdepth 1 -type d -mtime +7 -exec rm -rf {} + SCRIPT chmod +x /usr/local/bin/backup-docker-sites.sh echo "0 2 * * * /usr/local/bin/backup-docker-sites.sh" >> /etc/crontab八、总结
Docker + Nginx Proxy Manager 的组合将多站点管理从繁琐的命令行操作转变为直观的 Web 界面操作,HTTPS 证书申请、反向代理配置一键完成,容器隔离保证各站点互不影响。这套方案特别适合在单台香港 VPS 上同时运营 3~10 个网站的场景,充分利用服务器资源的同时保持良好的运维可控性。