后端服务线上部署
本文介绍了基于Docker和Kong API网关的后端服务线上部署方案。通过容器化部署user-service和order-service,并使用Kong作为API网关统一入口,仅对外暴露Nginx的80端口。文章详细说明了请求链路、Docker Compose配置、Kong声明式配置及Nginx反向代理设置,实现了服务隔离和API Key鉴权功能。该方案确保了服务安全性,同时提供了灵活的路由转发
本文主要记录一次 基于 Docker + API 网关(Kong) 的后端服务线上部署实践,个人觉得还有很多细节需要完善。
整体目标是:
后端服务容器化部署
通过 API 网关统一入口
对外仅暴露 Nginx 的 HTTP 端口
整体请求链路说明
一次接口请求的完整流程如下:
客户端(Apifox / 浏览器)
↓
Nginx(宿主机,仅暴露 80 端口)
↓
Kong API Gateway(Docker 容器)
↓
后端服务容器(user-service / order-service)
具体到请求示例:
访问: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命令
docker compose up -d --build #强制重新构建所有镜像并启动
docker compose up -d # 若本地已有镜像,仅启动容器
docker compose up -d --build order-service # 仅构建并启动指定服务
服务器目录结构:
docker-compose.yml 配置说明
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内容如下
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 内容如下:
_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 配置(宿主机)
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)