后端服务线上部署

本文主要记录一次 基于 Docker + API 网关(Kong) 的后端服务线上部署实践,个人觉得还有很多细节需要完善。

整体目标是:

bash
复制代码
后端服务容器化部署 通过 API 网关统一入口 对外仅暴露 Nginx 的 HTTP 端口

整体请求链路说明

一次接口请求的完整流程如下:

bash
复制代码
客户端(Apifox / 浏览器) ↓ Nginx(宿主机,仅暴露 80 端口) ↓ Kong API Gateway(Docker 容器) ↓ 后端服务容器(user-service / order-service)

具体到请求示例:

bash
复制代码
访问:http://域名或者IP地址/api/user/health ↓ Nginx 将请求转发至: http://127.0.0.1:8000/api/user/health (8000 端口由 Kong 使用) ↓ Kong 根据路由规则转发至: http://user-service:30122/health

其中:

8000 端口 仅在宿主机本地监听

30122 / 30222 等端口 仅存在于 Docker 内部网络

部署前准备

在开始部署前,需要准备:

1、已完成开发的后端服务(我这里是user-service和order-service) ,有一个/health接口 返回{"status":"ok"} 表示服务正常启动

2、一台服务器:已安装 Docker 与 Docker Compose、Nginx

常用的docker compose命令

bash
复制代码
docker compose up -d --build #强制重新构建所有镜像并启动 docker compose up -d # 若本地已有镜像,仅启动容器 docker compose up -d --build order-service # 仅构建并启动指定服务

服务器目录结构: 在这里插入图片描述

docker-compose.yml 配置说明

bash
复制代码
version: "3.9" networks: backend: driver: bridge services: kong: image: kong:3.6 container_name: kong restart: unless-stopped #自动重启 environment: KONG_DATABASE: "off" KONG_DECLARATIVE_CONFIG: /kong/kong.yml KONG_PROXY_ACCESS_LOG: /dev/stdout KONG_ADMIN_ACCESS_LOG: /dev/stdout KONG_PROXY_ERROR_LOG: /dev/stderr KONG_ADMIN_ERROR_LOG: /dev/stderr KONG_LOG_LEVEL: info volumes: - ./kong/kong.yml:/kong/kong.yml ports: - "127.0.0.1:8000:8000" # 仅宿主机可访问 - "127.0.0.1:8001:8001" # Kong Admin(本地管理) networks: - backend user-service: build: context: ./user-service dockerfile: Dockerfile image: user-service:latest container_name: user-service restart: unless-stopped expose: - "30122" # 仅 Docker 网络内可见 - "31122" networks: - backend order-service: build: context: ./order-service dockerfile: Dockerfile image: order-service:latest container_name: order-service restart: unless-stopped expose: - "30222" - "31222" networks: - backend

关键点说明:

expose 不会占用宿主机端口

后端服务只能被 Kong 或同一 Docker 网络内的容器访问

外部流量必须经过 Nginx → Kong

后端服务镜像构建(多阶段构建)

我的后端服务是使用kratos写的,如果是springboot项目,可以让ai去给你生成一个 Dockerfile文件 Dockerfile内容如下

bash
复制代码
FROM golang:1.22 AS builder COPY . /src WORKDIR /src RUN GOPROXY=https://goproxy.cn make build FROM debian:stable-slim RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ netbase \ tzdata \ && rm -rf /var/lib/apt/lists/* COPY --from=builder /src/bin /app COPY ./configs /data/conf VOLUME /logs WORKDIR /app EXPOSE 30122 EXPOSE 31122 #运行服务 CMD ["./user-service", "-conf", "/data/conf", "-env", ""]

Kong 配置(声明式)

修改 kong.yml 后,需要重启 Kong 容器:

docker compose restart kong

kong.yml 内容如下:

bash
复制代码
_format_version: "3.0" #定义apikey的值,所有服务只要使用下面某个apikey的值,都可以鉴权成功 consumers: - username: user-service-consumer keyauth_credentials: - key: test1 - username: order-service-consumer keyauth_credentials: - key: test2 services: - name: user-service # 因为 Kong 和 user-service 在同一个 Docker 网络里 url: http://user-service:30122 routes: - name: user-route paths: - /api/user strip_path: true #把 /api/user 从路径中去掉,再转发给后端,因为我后端写的api地址是/health,前面没有/api/user plugins: - name: key-auth # 使用Kong 官方的 API Key 鉴权插件 config: key_names: - apikey hide_credentials: true # apikey不转发给后端接口,只给kong鉴权用 - name: order-service url: http://order-service:30222 routes: - name: order-route paths: - /api/order strip_path: true plugins: - name: key-auth config: key_names: - apikey hide_credentials: true

Nginx 配置(宿主机)

bash
复制代码
server { listen 80; # 监听80端口 server_name <填写域名或者ip地址>; #匹配并处理所有以 /api/ 开头的请求路径 location /api/ { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 3s; proxy_send_timeout 10s; proxy_read_timeout 10s; } }

避坑点:location 与 proxy_pass 末尾的 / 在使用 Nginx 反向代理时,location 与 proxy_pass 末尾是否带 /,会直接影响请求路径的转发结果,这是一个非常容易被忽略但影响极大的问题。

测试

携带正确的apikey 在这里插入图片描述 携带错误的apikey 在这里插入图片描述

整体方案总结

后端服务全部运行在 Docker 容器中,服务端口仅在 Docker 内部网络暴露

外部访问统一经由 Nginx + Kong,并且访问接口时,需要在headler中携带apikey

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
hhj
下载 APP