前言

前面文章

聊到了如何在Rhel系统安装Docker,安装好之后先不要着急安装服务,先聊一聊服务代理,或者服务网关。

反向代理

首先什么是正向代理和反向代理。这两个概念可以从客户端请求为第一人称的角度出发。客户端发送请求,对于请求报文进行转发,也就是在请求出口的位置比如VPN之类的Proxy可以理解为正向代理,正向代理通常会代理客户端所有的出口请求。

反向代理是在客户端数据请求到服务端之后服务端入口并不真正的负责请求回复而是从后端服务或者后端其他主机获取请求再回复给客户端,这里可以理解代理的是客户端返回数据的代理叫做反向代理。

Nginx做反向代理

通常一个最简单的网站可以由LAMP(Linux Apache Mysql Php)组件构成,这种架构下由Apache直接面对客户端请求,对中小网站的请求来说通常问题不大,但是对于C10k的大体量的网站Apache会有些力不从心。可以使用Nginx高性能网络服务器挡在Apache前面作为Apache的带刀护卫(Redis和Mysq的关系类似),由Nginx直接面对客户端请求,Nginx为什么性能会比Apache高这里不过多展开,主要是因为Nginx在底层架构设计时使用了当时比较先进的epoll IO复用技术。同时使用守护进程和Worker进程分离,这样可以动态调整Worker进程的数量的同时可以支持在不停止服务的情况下实现动态加载配置文件,不仅如此Nginx还可以热升级,等等。

Nginx做反代的优点

Nginx挡在Apache前面网站架构就升级为LNAMPNginx直接面向连接的同时还可以作为高性能的反向代理。不仅可以代理请求到本主机的请求,还可以代理远程主机,并且可以实现负载均衡,动静态资源分离,静态资源缓存,URL重写,SSL加密,等等。Nginx最为代理服务器或者网关性能和可玩性还是比较高的。

Nginx作为反向代理通常做法是配置文件中Include一个自定义服务文件夹,然后在自定义文件夹下面定义各种代理配置文件,定义好代理配置执行nginx -s reload如果配置没有错误代理服务就启动成功了。

Nginx做反代的缺点

  • 每次代理的配置都需要手动进行编写,对于同一种类型的代理重复性配置工作比较多。
  • 每次配置完成都要执行nginx -s reload
  • 对于SSL证书的管理和配置比较繁琐,需要自己对证书的有效性进行维护。前几个月免费申请证书有效期从1年变成了3个月,也就是说每3个月就要对证书进行一次配置。很是头大。
  • 不能自动进行后端服务发现。

Nginx Proxy Manager

基于上面个人使用配置的复杂性,个人使用推荐Npm(Github地址)作为前端代理(基于OpenRestry)。使用Npm可以方便的进行证书管理,代理配置,配置完成也不需要再手动执行nginx -s reload即可生效。

Docker Compose安装Npm

services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'
      - '81:81'
      - '443:443'
    volumes:
      - ./stack/data/app:/data
      - ./stack/data/letsencrypt:/etc/letsencrypt
        #- ./stack/config/force-ssl.conf:/etc/nginx/conf.d/include/force-ssl.conf #特殊端口下需要映射,正常端口不需要.

对于上面配置文件做一下说明,首先逻辑卷的目录划分,可以看到都是以stack开头,这里每个docker compose启动的服务都是一个stack这个在portainer.io(docker的管理可视化服务)也是这样描述的。然后data是该stack所需要的数据目录。

对于force-ssl.conf这里为什么要进行特殊映射,原因是默认Npm强制ssl时会使用443端口作为HTTPS的默认端口。个人家庭网络环境即使申请了公网IP,443,80,8080端口也是被封禁的,所以对于家庭网络需要重写该配置文件。下面是/stack/config/force-ssl.conf配置文件的内容:

set $test "";
if ($scheme = "http") {
        set $test "H";
}
if ($request_uri = /.well-known/acme-challenge/test-challenge) {
        set $test "${test}T";
}
if ($test = H) {
        return 301 https://$host:9443$request_uri;
}

这里的9443端口需要根据自己配置的HTTPS端口进行修改。

启动Npm

有了compose配置文件,在该配置文件目录下直接docker compose up -d启动即可。

Npm的安装和证书配置

服务启动之后,只需要通过81端口即可访问Npm的后台管理。如图:

image-20241229112323803

第一次启动的默认的用户名密码需要使用docker container logs npm-app-1查看,如图

image-20241229112828040

登录管理后台后进行用户名和密码的重置。

image-20241229113224599

他的功能不是很复杂,Dashboard是展示面板,显示当前代理配置信息。Hosts是主要的代理配置模块,主要使用的功能就是如此。后面SSL Certifcates就是SSL自动证书管理的地方。

SSL Certifcates配置通常会使用Let`s Encypt进行免费证书的申请和管理。

image-20241229113633013

证书配置这里Domain Names,对于个人使用的域名通常都是一个,这里填写时最好使用通配域名申请证书,这样配置所有其他服务可以复用该证书,我这里使用的是 *.zhangshuocauc.cn zhangshuocauc.cn域名,如图:

image-20241229114440645

这里的邮箱填写管理域名的邮箱,然后勾选Use DNS Challege,勾选后会选择运营商,我用的是腾讯云,填写接口的ID和KEY(这里根据自己域名提供商进行不同的配置,关于id和key如何获取根据自己的运营商Google即可)点击Save保存即可。

配置正确的情况下,NPM会自动管理证书,在证书过期时会提前进行申请更新,省去了管理证书的麻烦。

Npm配置代理

Hosts点击add proxy host即可如图:

image-20241229115028746

按自己需求填写和勾选即可,SSL那里可以勾选Force SSL,当进行HTTP请求时,Npm会自动转换为HTTPS,转换规则转发到自定义SSL端口在前面安装时有说明。

在全站Docker环境下,通常IP这里填写Docker主地址即可,即172.17.0.1,后面端口填写服务的暴露端口。

总结

Npm进行服务的代理会比直接配置Nginx要方便很多,对于个人使用基本够用。网站全部迁移Docker时也是使用的Npm,但是Npm对于我个人使用上有一些小问题。

  1. Npm不支持HaProxy代理协议,也就是通过HaProxy代理过来的无法使用Npm获得代理请求的真实IP地址,无法完成审计。这个我查找了项目Github上的提问,作者明确表示Npm使用对象是中小型企业或者个人,不会考虑支持该配置。其实支持也比较简单,需要修改Npm生成的配置文件,然后nginx -s reload即可生效,但是如果在后台进行配置修改之后手动修改的会被移除。
  2. 使用Npm代理的服务都需要映射主机端口,也就是可以通过宿主机IP+端口直接访问,安全性没有保障。
  3. 没有服务自动发现功能,也就是说所有要上线的服务都需要事先在Npm管理后台进行配置。
  4. 数据请求流比较长:主机端口->Docker->Npm->主机端口->Docker->服务,数据链路越长性能会受影响。

--EOF

最后修改:2025 年 01 月 11 日
如果觉得我的文章对你有用,请随意赞赏