轻量云服务器实战:Docker部署NPM打造可视化反向代理与自动SSL
## 一、 引言:为什么需要可视化反向代理?
随着个人云主机的普及,越来越多的开发者开始在单台云服务器上同时运行多个服务,例如:
- 个人博客系统(如 Halo、WordPress)
- 状态监控看板(如 Uptime Kuma)
- 私有知识库或轻量网盘(如 Memos、Alist)
- 各种自定义后端 API 服务
这些服务默认运行在不同的内网端口(如 3000、3001、8080、5230 等)。如果直接对外暴露端口,不仅容易引发安全隐患,而且不支持优美的独立子域名以及统一的 HTTPS 加密访问。
传统方案通常是安装原生 Nginx,然后手写大量的 `upstream` 和 `server` 块配置文件,并结合 `certbot` 定时脚本申请证书。但这种做法存在几大痛点:
1. **语法门槛高**:反向代理 WebSocket、报头重写、跨域配置稍有不慎就会导致 502/504 错误。
2. **证书管理碎**:多个二级域名需要逐个配置证书路径,容易出现续签脚本失效或证书遗忘续期。
3. **运维成本高**:每次新增服务都需要 SSH 登录终端,修改配置文件并 `nginx -s reload`。
**Nginx Proxy Manager(简称 NPM)** 彻底解决了这一问题。它基于 OpenResty 开发,集成了简洁直观的 Web UI、自动化的 Let's Encrypt 证书签发引擎、灵活的访问控制列表(Access Lists)和端口转发功能,运行时内存仅占用约 100MB~150MB,非常适合运行在 1核1G 或 2核2G 的轻量云服务器上。
---
## 二、 部署准备与环境检查
本文以 Ubuntu 24.04 LTS 云服务器环境为例。在开始前,请确认服务器已具备 Docker 及 Docker Compose 运行环境。
### 1. 检查 Docker 状态
在终端执行以下命令,验证 Docker 引擎状态:
```bash
docker --version
docker compose version
```
若尚未安装 Docker,推荐执行官方一键安装脚本:
```bash
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo systemctl enable --now docker
```
### 2. 检查 80 与 443 端口占用
Nginx Proxy Manager 需要接管宿主机的 HTTP(80)与 HTTPS(443)流量,请确保当前没有其他 Web 服务器(如 Apache 或旧版 Nginx)占用这两个核心端口:
```bash
sudo lsof -i :80
sudo lsof -i :443
```
如果已有系统原生 Nginx 在运行,可先将其停止并禁用:
```bash
sudo systemctl stop nginx
sudo systemctl disable nginx
```
---
## 三、 编写 Docker Compose 编排文件
我们将所有的容器配置与持久化数据收敛在 `/opt/containers/nginx-proxy-manager` 目录下,便于日后统一备份与迁移。
### 1. 创建工作目录
```bash
sudo mkdir -p /opt/containers/nginx-proxy-manager
cd /opt/containers/nginx-proxy-manager
```
### 2. 编写 `docker-compose.yml`
创建编排文件:
```bash
sudo vim docker-compose.yml
```
写入以下配置内容:
```yaml
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
# 接受公网 HTTP 流量
- '80:80'
# NPM 可视化管理后台端口(建议配合防火墙做限制)
- '81:81'
# 接受公网 HTTPS 流量
- '443:443'
volumes:
# NPM 数据库与配置文件
- ./data:/data
# Let's Encrypt 证书及密钥存储
- ./letsencrypt:/etc/letsencrypt
environment:
- TZ=Asia/Shanghai
# 禁用不必要的崩溃上报,降低资源消耗
- DISABLE_IPV6=true
deploy:
resources:
limits:
memory: 384M
```
> **架构与资源设计说明**:
> - **轻量级内置存储**:NPM 默认采用轻量级 SQLite 数据库存储在 `./data/database.sqlite` 中,无需额外启动 MySQL/MariaDB 容器,直接节省 200MB+ 内存开销。
> - **证书安全隔离**:`./letsencrypt` 目录挂载在宿主机,即便容器销毁重建,申请好的 SSL 证书与私钥也不会丢失。
> - **内存上限保护**:通过 `limits.memory: 384M` 设定防线,防止极端突发流量或扫描撞库引发宿主机 OOM。
---
## 四、 服务启动与初始化配置
### 1. 拉取镜像并启动
在 `/opt/containers/nginx-proxy-manager` 目录下执行:
```bash
sudo docker compose up -d
```
查看容器启动日志,确保初始化迁移顺利完成:
```bash
sudo docker compose logs -f
```
看到终端输出 `[Setup ] Setup Complete` 类似字样后,按 `Ctrl + C` 退出日志跟踪。
### 2. 首次登录与修改安全凭证
在浏览器中访问:`http://<你的服务器公网IP>:81`。
* **初始默认账号**:`admin@example.com`
* **初始默认密码**:`changeme`
首次登录成功后,系统会强制弹出个人信息与密码修改弹窗:
1. **修改管理员邮箱**:填写你的真实常用邮箱(该邮箱后续也将用于接收 Let's Encrypt 证书即将过期的安全提醒通知)。
2. **设置强密码**:设置包含字母、数字及特殊符号的复杂密码,并立即保存。
---
## 五、 实战:三分钟完成服务反代与 SSL 证书自动签发
假设我们在云服务器本地运行了一个 Web 容器(如前面部署在 `127.0.0.1:3001` 的 Uptime Kuma 监控看板),并且我们拥有域名 `example.com`,现在希望通过 `status.example.com` 实现全自动 HTTPS 加密访问。
### 1. 配置 DNS 域名解析
前往你的域名 DNS 控制台(如 Cloudflare、阿里云或华为云 DNS),新增一条 A 记录:
- **主机记录**:`status`
- **记录类型**:`A`
- **记录值**:填写你的云服务器公网 IP
- **TTL**:默认即可
### 2. 在 NPM 中添加反向代理规则(Proxy Host)
1. 登录 NPM 控制台,点击顶部导航栏的 **“Hosts” -> “Proxy Hosts”**。
2. 点击右上角 **“Add Proxy Host”** 按钮。
3. 在 **“Details”** 选项卡中进行如下配置:
- **Domain Names**:填写 `status.example.com` 并按回车确认。
- **Scheme**:选择 `http`。
- **Forward Hostname / IP**:填写容器所在宿主机内网 IP 或使用宿主机别名。若容器与 NPM 处于同一宿主机,建议填写宿主机的内网 IP,或直接使用 Docker 内部网络别名;若使用 host 模式直接填写 `172.17.0.1` 或宿主机内网 IP。
- **Forward Port**:填写目标服务的内部端口(例如 `3001`)。
- **开启功能选项**:
- 勾选 **Cache Assets**(静态资产缓存,加速加载)
- 勾选 **Block Common Exploits**(开启常见 Web 漏洞与恶意注入过滤防护)
- 勾选 **Websockets Support**(如后端是实时通信或 Socket 页面,务必勾选)
### 3. 一键申请并配置免费 SSL 证书
切换到 **“SSL”** 选项卡:
1. **SSL Certificate**:下拉选择 **“Request a new SSL Certificate”**(申请新证书)。
2. 勾选 **Force SSL**(强制将 HTTP 80 重定向到 HTTPS 443)。
3. 勾选 **HTTP/2 Support**(开启 HTTP/2 协议,大幅提升多请求并发传输性能)。
4. 勾选 **HSTS Enabled**(开启严格传输安全协议,防止降级劫持)。
5. 填入你的电子邮箱,并勾选 **“I Agree to the Let's Encrypt Terms of Service”**。
6. 点击右下角 **“Save”**。
NPM 会自动与 Let's Encrypt ACME 服务器发起 HTTP-01 验证挑战,验证通过后自动写入 Nginx 配置并平滑加载。整个过程通常在 5~15 秒内自动完成,无需敲击任何一行黑屏命令!
更省心的是:**NPM 会在后台定时自动巡检,并在证书到期前 30 天自动静默续签**,彻底告别证书过期导致的网站告警。
---
## 六、 进阶安全加固:Access Lists(访问控制列表)
轻量云服务器上的某些私有服务(例如管理后台、测试端点)不希望对公网完全开放。NPM 提供了开箱即用的 **Access Lists** 功能,无需写正则即可实现双重安全防护。
### 1. 创建访问控制策略
1. 点击导航栏 **“Access Lists” -> “Add Access List”**。
2. **Name**:填写规则名称,如 `Internal-Only`。
3. **Authorization(Basic Auth 密码锁)**:
- 添加用户名和密码。即使外部用户获知了访问域名,也必须输入此账号密码才能进入后续页面。
4. **Access(IP 白名单限制)**:
- 在白名单列表中添加信任的固定 IP 地址(例如你家庭宽带公网 IP 或公司办公网段)。
- 勾选 **Satisfy Any**(满足任一条件即可)或 **Satisfy All**(必须同时满足 IP 白名单与账号密码)。
5. 点击 **Save** 保存。
### 2. 绑定策略到目标站点
返回 **Proxy Hosts** 列表,编辑对应的站点,在 **Access List** 下拉列表中选择刚刚创建的 `Internal-Only`。未在白名单内或输入错误密码的用户,将被直接阻断并返回 `401 Unauthorized` 或 `403 Forbidden`。
---
## 七、 备份与灾难恢复方案
由于我们采用了清晰的目录隔离挂载,整个系统的灾备方案非常优雅纯粹:
```bash
#!/bin/bash
# 保存为 /opt/containers/nginx-proxy-manager/backup_npm.sh
BACKUP_PATH="/opt/backup/npm"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_PATH
# 压缩持久化数据与证书库
tar -czvf "$BACKUP_PATH/npm_backup_$DATE.tar.gz" \
-C /opt/containers/nginx-proxy-manager data letsencrypt docker-compose.yml
# 仅保留最近 14 天的备份
find $BACKUP_PATH -type f -name "npm_backup_*.tar.gz" -mtime +14 -delete
```
加入 Linux `crontab` 定时器即可实现每周自动化归档备份。如果日后需要更换服务器,只需将备份包解压到新服务器的对应目录,执行 `docker compose up -d` 即可实现全量无缝秒级复活!
---
## 八、 总结与最佳实践建议
在本文中,我们通过 Docker Compose 在轻量云服务器上落地了一套开箱即用的反向代理中枢。Nginx Proxy Manager 不仅保留了 Nginx 高性能、低开销的底层内核,更通过现代化的图形交互打破了配置繁琐的壁垒。
**实践建议总结**:
1. **端口安全管控**:管理后台使用的 `81` 端口建议在云安全组中仅对管理员特定 IP 开放,或者通过 SSH 本地端口转发访问,避免管理后台直接裸奔公网。
2. **充分利用 WebSocket 开关**:对于长轮询、实时推送类应用(如即时通讯、在线终端、监控面板),务必在站点配置中开启 Websockets Support。
3. **域名规划清晰**:建议使用泛解析(如 `*.yourdomain.com`)配合二级域名,配合 NPM 实现“一个域名开箱一个新服务”,大幅提升个人云上实验与开发的交付效率。
- 点赞
- 收藏
- 关注作者
评论(0)