使用 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。以下是一些基本步骤:

  1. 安装 Docker 和 Docker Compose:如果尚未安装,请先安装 Docker 和 Docker Compose。

  2. 创建 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就是这个,你可以根据你实际情况来。
npm_proxy1
配置完成后就可以访问了,不过现在还是http协议,下一步我们来添加证书

添加证书管理

在npm中使用ssl证书管理有两种方式,一种是生成现有证书,另一种是通过Certbot自动通过Let’s Encrypt自动刷新证书,这里介绍第二种。我的是在腾讯云买的,所以以此为例,其他云服务也是大差不差的。
证书申请可以使用泛域名,不过只支持一层,如我这里的设置,同时aa.wushr.cnbb.wushr.cn 都可以使用这个证书,但是aaa.bbb.wushr.cn就不支持了。

申请 api_token

打开DNSPod后台切换到DNSPod Token,点击创建秘钥名称,生成
dnspod
复制id和token,回到Npm后台,填入到dns_dnspod_api_token中,记得把上面的邮箱换成自己的邮箱地址。
npm-ssh
点击保存NPM就会执行脚本申请证书了,如果申请失败就多试几次,或者看最后的常见错误。
npm_ssl_list

配置https

回到配置代理的面板,点击刚才配置的域名,切换到SSL面板,选择证书
npm_proxy_ssl
再访问你的域名,就会变成https了
bloghttps

Default Site 配置成https访问

现在直接访问没设置代理的域名,会发现是http的,强制加上https会报错。
default_site_ssl_fail
那是因为默认情况下,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了
default_site_ssh

常见错误

执行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