经常会碰到一些项目,其服务虽然在线上是通过同一个域名公开访问的,但是开发时,却是由多个不同的子项目组成的。在本地可以单独启动单独测试,一般是通过端口区分。在本地联调时,不想单独做很复杂的配置的话,就需要模拟线上环境,在同一个端口下把多个项目跑起来。这就需要用到反向代理。

假设有两个项目,单独启动时,分别运行在 5001 和 5003 端口,但是现在希望在本地能够通过 https://local.dev.example.com:5000 来访问,其中 /client/* 指向 5003 项目,而其他路由指向 5001 端口。

域名

在本地,可以配置一个 hosts (/etc/hosts)来模拟线上环境: csharp 127.0.0.1 localhost 255.255.255.255 broadcasthost ::1 localhost

127.0.0.1 local.dev.example.com

用 docker compose nginx 做反向代理

当然也可以用 nginx,如果不想安装和配置,建议使用 Docker compose 方案:

yaml version: 3.4

services: localproxy: build: context: ./LocalProxy dockerfile: Dockerfile ports: - 5000:80 networks: default: aliases: - local.dev.example.com

client:
build:
	context: .
	dockerfile: client/Dockerfile
ports:
	- 5003:80

server: build: context: . dockerfile: server/Dockerfile ports: - 5001:80

networks: default: name: example_network

以上,通过 docker compose up 启动后,将 server 项目的 5001 映射到 80 端口,而 client 项目的 5003 也映射到 80 端口。而反向代理服务将 5000 映射到 80 端口。这样就可以通过 https://local.dev.example.com:5000 的方式访问到 client 和 server 了。

client 和 server 的 Dockerfile 根据具体的项目来写,而 localproxy 的 Dockerfile 是基于 nginx 的,内容如下:

dockerfile FROM nginx:alpine COPY nginx.conf /etc/nginx/nginx.conf RUN apk add --update openssl && rm -rf /var/cache/apk/* RUN mkdir -p /etc/nginx/ssl/certs RUN mkdir -p /etc/ssl/private/ RUN openssl req -x509 -nodes -days 365 -subj /C=CA/ST=QC/O=Example, Inc./CN=local.dev.example.com -addext subjectAltName=DNS:local.dev.example.com -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt; EXPOSE 80 EXPOSE 443 EXPOSE 5000

虽然完全可行,但是比较麻烦。如果不想用 Docker compose 也不想用 nginx,就可以使用 Caddy 来完成同样的事情:

用 caddy 来做反向代理

同样也需要在 hosts 里增加域名。

安装 caddy

如果没有安装,可以通过 brew install caddy(Mac)或者 choco install caddy(Windows)安装 caddy。

添加 Caddyfile

在项目的根目录下新建 Caddyfile 文件,内容如下: dockerfile https://local.dev.example.com:5000 {

tls internal

reverse_proxy /client/* http://local.dev.example.com:5003

reverse_proxy http://local.dev.example.com:5001

}

运行 caddy

shell caddy run

分别启动项目后,同样可以使用 https://local.dev.example.com:5000 来访问 server 和 client 了,效果和 nginx 方案完全一样!