使用 Docker Compose 部署 Nginx Proxy Manager 作为网关
介绍 Nginx
Nginx 是一款高性能的开源反向代理服务器,用于处理网络流量并提供负载均衡、缓存、SSL/TLS 加密以及许多其他功能。不过虽然Nginx 在许多方面都表现出色,但配置它可能会变得相当繁琐:
-
语法复杂性:Nginx 配置文件使用自定义的语法,这使得理解和编写配置文件变得复杂,特别是对于初学者而言经常会出错。
-
手动证书管理:配置 SSL/TLS 证书通常需要手动操作,包括证书的购买、更新和配置,如果是来此加密的免费证书,没三个月都需要手动更新一次也挺麻烦的。
-
动态路由:当需要添加代理或反向代理服务时,必须手动编辑 Nginx 配置文件以添加新的路由规则。
于是需要寻找一个工具简化工作,Nginx Proxy Manager正好可以满足要求。
Nginx Proxy Manager 的便利性
Nginx Proxy Manager (NPM) 是一个基于 Web 的管理工具,旨在简化 Nginx 配置的管理。它提供了一个直观的用户界面,使得配置 Nginx 变得轻而易举。
以下是 Nginx Proxy Manager 的一些便利功能:
-
用户友好的界面:NPM 提供了一个易于使用的 Web 界面,让您可以直观地管理 Nginx 配置,而不必深入研究配置文件的语法。
-
证书管理:NPM 允许您轻松管理 SSL/TLS 证书,包括自动续订。
-
动态路由:通过 NPM,您可以轻松添加、编辑和删除代理规则,而无需手动编辑配置文件。
使用 Docker Compose 部署 NPM
要部署 Nginx Proxy Manager,您可以使用 Docker Compose。以下是一些基本步骤:
-
安装 Docker 和 Docker Compose:如果尚未安装,请先安装 Docker 和 Docker Compose。
-
创建 Docker Compose 文件:创建一个名为
docker-compose.yml
的文件,并在其中定义 Nginx Proxy Manager 的容器。
version: '3'
services:
nginx-proxy-manager:
image: 'chishin/nginx-proxy-manager-zh:latest' ## 这个是中文镜像,官方镜像是jc21/nginx-proxy-manager:latest
restart: always
container_name: nginx-proxy-manager
hostname: nginx-proxy
environment:
# Mysql/Maria connection parameters:
DB_MYSQL_HOST: "mysql8"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD: "npm"
DB_MYSQL_NAME: "npm"
TZ: Asia/Shanghai
networks:
- my-net ## 指定docker网络,因为我的服务都是关联在这个网络下的
ports:
- '80:80' # 不建议修改端口
- '81:81' # 可以把冒号左边的 81 端口修改成你服务器上没有被占用的端口
- '443:443' # 不建议修改端口
volumes:
- ./data:/data # 点号表示当前文件夹,冒号左边的意思是在当前文件夹下创建一个 data 目录,用于存放数据,如果不存在的话,会自动创建
- ./letsencrypt:/etc/letsencrypt # 点号表示当前文件夹,冒号左边的意思是在当前文件夹下创建一个 letsencrypt 目录,用于存放证书,如果不存在的话,会自动创建
networks: ## 指定docker网络,因为我的服务都是关联在这个网络下的
my-net:
external: true
启动容器:在包含 docker-compose.yml 文件的目录中运行以下命令启动容器:
docker-compose up -d
使用浏览器访问 http://your_server_ip:81,然后按照界面上的指示进行设置,包括初始化密码之类的。
添加代理
先把你需要代理的域名解析到你的IP地址上,然后就可以添加代理了。
比如我的博客域名是blog.wushr.cn,转发内部服务的IP是gosonic,因为我的博客docker-compose.yaml文件中hostname就是这个,你可以根据你实际情况来。
配置完成后就可以访问了,不过现在还是http协议,下一步我们来添加证书
添加证书管理
在npm中使用ssl证书管理有两种方式,一种是生成现有证书,另一种是通过Certbot自动通过Let’s Encrypt自动刷新证书,这里介绍第二种。我的是在腾讯云买的,所以以此为例,其他云服务也是大差不差的。
证书申请可以使用泛域名,不过只支持一层,如我这里的设置,同时aa.wushr.cn、bb.wushr.cn 都可以使用这个证书,但是aaa.bbb.wushr.cn就不支持了。
申请 api_token
打开DNSPod后台切换到DNSPod Token,点击创建秘钥名称,生成
复制id和token,回到Npm后台,填入到dns_dnspod_api_token
中,记得把上面的邮箱换成自己的邮箱地址。
点击保存NPM就会执行脚本申请证书了,如果申请失败就多试几次,或者看最后的常见错误。
配置https
回到配置代理的面板,点击刚才配置的域名,切换到SSL面板,选择证书
再访问你的域名,就会变成https了
Default Site 配置成https访问
现在直接访问没设置代理的域名,会发现是http的,强制加上https会报错。
那是因为默认情况下,NPM会监听80/443端口然后根据设置进行代理,被代理的域名就可以走https协议,没有设置的域名就会走设置-》Default Site的网页,但是这个网页默认是http的,如果你和我一样希望全站都是https,可以参考下面的的设置。
修改nginx文件
NPM内部也是有nginx服务的,默认配置文件在容器内的/etc/nginx文件里面,先复制出来,
sudo docker cp nginx-proxy-manager:/etc/nginx ./
cd nginx/conf.d/
cp default.conf default.conf_back ##备份一下
sudo vim nginx/conf.d/default.conf
然后复制下面的覆盖配置,这里需要注意证书的位置,每个人路径是不一样的,因为我申请的是泛域名证书,可以到data/nginx/proxy_host
文件下面看看有那个代理配置的域名是同级的就行,如果是指定域名的话那就换一个吧。另外这个证书地址是容器内的地址,不是我们宿主机的地址。
# First 443 Host, which is the default if another default doesn't exist
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
access_log /data/logs/default-host_access.log combined;
error_log /data/logs/default-host_error.log warn;
# Let's Encrypt SSL
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/ssl-ciphers.conf;
ssl_certificate /etc/letsencrypt/live/npm-10/fullchain.pem; ## 证书
ssl_certificate_key /etc/letsencrypt/live/npm-10/privkey.pem; ## 证书
# Block Exploits
include conf.d/include/block-exploits.conf;
# Force SSL
include conf.d/include/force-ssl.conf;
root /data/nginx/default_www;
location / {
try_files $uri /index.html;
}
}
修改docker-compose.yaml文件
因为我们是把容器内的文件复制出来修改了,为了让配置生效,所以还需要把这个文件映射回去,这里修改docker-compose.yaml文件就行
#.....略略
volumes:
- ./nginx:/etc/nginx ## 增加这一句
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
#.....略略
然后执行docker-compose up -d
,在访问就是https了
常见错误
执行docker-compose up -d 后,访问不到后台,看日志 zope module not found
可以使用到docker-compose.yam所在的文件夹下执行
docker-compose logs -f
查看日志,如果有错误日志打印 **** module not found 的提示,可以执行
docker-compose exec nginx-proxy-manager sh
进入容器内,然后安装缺失的模块
pip install zope.interface
退出容器后执行
docker-compose restart