Logo
活死人の行知路

API网关


📅 | 📝 1888 字
#gateway

1什么是 API 网关

2Kong

2.1疑问?

1、关于 kong-migrations 是否会重置数据库?

答案是:不会。它非常安全。

kong migrations bootstrap 命令是幂等的。它的执行逻辑如下:

  • 首次启动:检测到数据库为空,它会建表并写入初始的架构数据。
  • 后续重启:它会先检查数据库中是否已经存在 Kong 的核心表(如 schema_migrations)。如果存在,它会直接输出类似 Database already initialized 的日志,然后以状态码 0 成功退出。

结论:在使用 Docker Compose 搭建Kong环境可以放心地让它每次随 docker-compose up -d 启动,它绝对不会清空或覆盖你已经在 Kong 中配置的路由、服务和插件数据。


2、关于 PostgreSQL 是否需要为 Kong 创建独立数据库?

答案是:强烈建议创建独立的逻辑数据库(Database)和独立的用户(Role)。


3、你部署在本地电脑(Windows / Mac / 本地 Linux)

如果你是在自己面前的电脑上跑的 Docker Compose,直接打开浏览器,访问以下本机地址即可(假设你没有修改 .env 中的默认端口):


4、你部署在远程云服务器(阿里云、腾讯云等)

因为服务都绑定了 127.0.0.1,所以你无法直接通过 http://服务器公网IP:8002 来访问这些控制台(这是极其安全的保护机制,防止黑客扫描后台)。

你有两种标准方式来访问它们:

4.1、方案 A:使用 SSH 隧道(最推荐,安全、免配 Nginx)

不需要在服务器上改任何配置。打开你本地电脑的终端(Mac/Linux)或 PowerShell/CMD(Windows),执行以下命令建立一条加密隧道:

# 将远程服务器的 8002(Kong) 和 13000(Grafana) 映射到你的本机电脑上
ssh -N -f -L 8002:127.0.0.1:8002 -L 13000:127.0.0.1:13000 root@你的云服务器公网IP

执行成功后,你在本地电脑的浏览器里直接输入 http://127.0.0.1:8002,流量就会通过加密隧道安全地转发到云服务器的 Kong 控制台上。

4.2、方案 B:通过 Nginx 反向代理并绑定域名

如果你的团队需要共同使用,或者你想提供公开的 API 网关服务,你需要利用脚本中已经启动的 nginx-proxy 容器来进行反向代理。

你可以将你的域名(例如 kong.yourdomain.com)解析到服务器公网 IP,然后在 ./nginx/conf.d/ 目录下新建一个配置文件,将外网的 HTTP(80)/HTTPS(443) 流量代理给内部的 127.0.0.1:80008002

⚠️ 安全警告

  • Kong 的代理入口(8000/8443)可以通过 Nginx 暴露给外网。
  • Kong 的 Admin API(8001)和 Manager UI(8002),以及其他后台(Nacos, Grafana 等)强烈建议只允许公司内网 IP 访问,或者配合 Nginx 的 auth_basic 增加一层账号密码验证!

5、集成DNS_RESOLVER是否配置 配置什么值?

这是一个非常关键的细节!在 Docker Compose 环境下部署 Kong 时,强烈建议配置 KONG_DNS_RESOLVER

5.1、是否需要配置? 需要。

原因: Kong 作为一个 API 网关,它的核心工作就是把流量转发给后端的微服务(比如你的 equipment-mgr)。在 Docker 网络中,这些微服务的 IP 是动态分配的,我们通常通过容器名(如 http://equipment-mgr:1301)来进行内网调用。 如果不明确告诉 Kong 去哪里解析这些容器名,Kong 内部的 Nginx 解析器有时会因为找不到合法的 DNS 服务器而报 host not found in upstream 错误。

5.2、配置什么值? 在 Docker 环境下,标准且最安全的配置值是: 127.0.0.11

127.0.0.11 是 Docker 引擎内置的内部 DNS 服务器地址。配置它之后,Kong 就能像魔法一样自动认识同处在 infra-internal 网络下的所有容器名字了。

如果你除了代理内网服务,还需要通过 Kong 代理访问公网上的外部 API(比如对接微信接口、支付宝接口),建议再加一个公共 DNS 作为兜底(例如阿里云的 223.5.5.5114.114.114.114)。

最终推荐值: 127.0.0.11, 114.114.114.114


3背景

如何配置动态路由?

比如我有一些微服务项目,web层提供http 接口,有user-web, eam-web两个微服务项目,分时是4301和4303两个端口,它们分别访问user-svc和eam-svc两个grpc项目,这两个端口分别是4302和4304,现在前端如果要访问后端,不可能将4301和4303都写到前端分别访问不同的服务,所以引入了kong,我这个场景该如何配置,我还要提供哪些内容

这是一个非常标准的微服务网关应用场景!你的思路完全正确:前端只需要知道 Kong 的一个统一入口(比如 8000 端口),由 Kong 根据请求的路径(Path)将流量智能地分发到后端的各个微服务。

在这个架构中,Kong 的作用是接管**外部(前端)到内部(Web 层)**的 HTTP 流量。至于 Web 层(4301/4303)调用 gRPC 层(4302/4304)的内部流量,通常直接通过内网互相调用(或借助 Consul)即可,不需要再经过 Kong 绕一圈。

下面我手把手教你如何通过刚刚搭建好的 Kong Manager (8002 端口) 来配置这个场景,以及你还需要准备什么。


3.1核心概念:Service(服务)与 Route(路由)

在 Kong 中,配置请求转发永远分为两步:

  1. Service(服务):告诉 Kong “后端真实的项目在哪里”(比如 user-web 的地址和端口)。
  2. Route(路由):告诉 Kong “前端怎么访问才能触发这个服务”(比如请求路径包含 /user-api)。

3.2第一步:在 Kong Manager 中配置 user-web

  1. 创建 Service

    • 打开 Kong Manager (http://127.0.0.1:8002),进入 default 工作空间。
    • 点击左侧菜单的 Gateway Services,点击页面 New gateway service
    • Service endpoint选择 Protocol, host, port, and path方式,如果服务配置了域名可以选择Full URL
    • 填写以下信息:
      • Name: user-web (起个好记的名字)
      • URL: http://你的目标IP或容器名:4301 (💡 注意:如果你的 user-web 和 Kong 在同一个 docker-compose 网络里,这里可以直接填 http://user-web:4301。如果不在同一个网络,你需要填写宿主机的局域网 IP,比如 http://192.168.1.100:4301。)
    • 点击 Save
  2. 创建 Route

    • 在刚才建好的 user 详情页,找到 Routes 模块,点击 New Route
    • 填写以下信息:
      • Name: user-route
      • Paths: 输入 /api/user 然后按回车(生成一个标签)。
      • Strip Path: 选择 YesNo。(极其重要,详见下方说明 👇)
    • 点击 Save

💡 核心抉择:Strip Path(剥离路径)该选 Yes 还是 No?

这是配置网关时最容易踩坑的地方,取决于你后端代码是怎么写的:

  • 情况 A(选 No):如果你前端请求 http://127.0.0.1:8000/api/user/login,Kong 会原封不动地把 /api/user/login 发给你的 user-web (4301)。这意味着你的 user-web 里的代码路由必须写成 @RequestMapping("/api/user/login")
  • 情况 B(选 Yes):如果你前端请求 http://127.0.0.1:8000/api/user/login,Kong 会把前缀 /api/user 砍掉,只把 /login 发给 user-web (4301)。这意味着你 user-web 里的代码路由只需要写 @RequestMapping("/login")

通常推荐使用 情况 B (Strip Path = Yes),这样后端代码更干净,不需要在代码里硬编码网关的前缀。


第二步:配置 eam-web

按照同样的逻辑,再配一套:

  1. Service:
    • Name: eam-web-service
    • URL: http://目标IP:4303
  2. Route:
    • Paths: /api/eam
    • Strip Path: 视你的代码逻辑而定。

配置完成后,前端只需要统一访问 http://127.0.0.1:8000/api/user/...http://127.0.0.1:8000/api/eam/...,Kong 就会自动完成分发!


第三步:你还需要提供/准备什么内容?

为了让这套流程在生产环境中完美运转,你还需要关注以下 3 点:

1.网络连通性 (Network Reachability)

Kong 必须能“看见”你的 4301 和 4303 端口。

  • 如果这两个 web 服务是跑在宿主机上的普通进程,确保防火墙放行了这两个端口。
  • 如果它们也是 Docker 容器,最省事的办法是让它们加入 Kong 所在的 app-infra-net 网络,这样 Kong 就能直接通过容器名(如 http://user-web:4301)调用它们。

2.CORS 跨域问题 (极其关键)

前端如果直接通过 Ajax/Axios 请求 Kong 的 8000 端口,100% 会遇到跨域报错(CORS)。 解决方案:不需要在你的 user-webeam-web 代码里写跨域逻辑!直接在 Kong Manager 里开启插件:

  • 点击左侧 Plugins -> New Plugin -> 搜索 CORS
  • 将其配置为全局(Global),允许所有的 Origins(或者指定前端域名),允许常用的 Methods (GET, POST, PUT, DELETE, OPTIONS) 和 Headers。
  • 保存后,Kong 就会自动帮你处理所有跨域请求。

3.鉴权逻辑(JWT/OAuth 等)的设计

目前前端请求是直接裸奔到后端的。你打算在哪里校验用户的登录状态和 Token? 是准备让 Kong 在网关层拦截(使用 Kong 的 JWT 插件),还是打算在你的 user-web 代码里自己写拦截器处理?


/api/user是什么值,根据什么来配置这个值,比如我的用户注册接口为/user/signup,我该如何配置

这是一个非常核心的问题!很多人刚用 Kong 的时候都会在这里绕晕。

简单直接地回答你:/api/user 这个值是你自己定的“网关前缀”,它不需要和你后端代码里写的真实路径完全一样。

配置这个值,主要取决于你想让前端怎么访问你的接口,以及你是否开启了 Strip Path(剥离路径)

结合你的真实场景(后端真实接口是 /user/signup),我为你梳理两种最常用的配置方案:

方案一:原样透传(最简单,所见即所得)

这种模式下,前端请求的路径和后端代码写的路径一模一样。Kong 只负责做域名和端口的转发,不修改路径。

  • 你的诉求:前端通过 http://127.0.0.1:8000/user/signup 访问。
  • Kong 配置逻辑
    • Service URLhttp://user-web:4301
    • Route Paths:配置为 /user (意思是只要请求以 /user 开头,就交给这个服务)。
    • Strip Path:设置为 No
  • 流量流向
    1. 前端请求:http://127.0.0.1:8000/user/signup
    2. Kong 匹配到前缀 /user,找到 user-web-service
    3. 因为 Strip Path = No,Kong 原封不动保留路径。
    4. Kong 实际请求后端:http://user-web:4301/user/signup

方案二:网关加前缀(微服务最佳实践)

微服务架构中,我们通常会在网关层加上 /api 或者 /v1 这样的统一前缀,方便管理和区分。但后端的 Java/Go 代码里不想写这些恶心的前缀。

  • 你的诉求:前端通过 http://127.0.0.1:8000/api/user/signup 访问。但后端代码依然只写 @RequestMapping("/user/signup")
  • Kong 配置逻辑
    • Service URLhttp://user-web:4301
    • Route Paths:配置为 /api (意思是只要以 /api 开头的都归我管)。
    • Strip Path:设置为 Yes
  • 流量流向
    1. 前端请求:http://127.0.0.1:8000/api/user/signup
    2. Kong 匹配到前缀 /api,找到 user-web-service
    3. 因为 Strip Path = Yes,Kong 会像剥洋葱一样把 /api 砍掉,只剩下 /user/signup
    4. Kong 实际请求后端:http://user-web:4301/user/signup

总结:我该如何抉择?

  1. 如果你希望前端的 URL 漂亮统一(比如 网关IP:8000/api/项目名/具体接口),那么就在 Kong 的 Route 里把 Path 设为 /api/项目名,并且开启 Strip Path = Yes
  2. 如果你的老项目不想折腾,前端一直都是直接访问 /user/signup 的,那就把 Route Path 设为 /user,并且关闭 Strip Path = No

为了让你更直观地感受 Kong 是如何拼接和裁剪 URL 的,我为你生成了一个交互式的动态路由模拟器。你可以修改前缀和开启/关闭 Strip Path,看看最终到达你后端的 URL 会变成什么样:

{"component":"LlmGeneratedComponent","props":{"height":"600px","prompt":"创建一个 Kong API 网关 URL 路由逻辑模拟器。\n\n1. 目标:演示前端请求路径、Kong Route Path、Strip Path 设置与最终到达后端的 URL 之间的转换关系。\n2. 初始数据状态:\n   - 后端服务 (Service URL): `http://user-web:4301`\n   - Kong 路由前缀 (Route Path): `/api`\n   - 剥离路径 (Strip Path): `开启 (Yes)`\n   - 前端模拟请求路径: `/api/user/signup`\n3. 布局策略:Form Layout (表单在左/上,动态结果可视化在右/下)。\n4. 输入控件:\n   - 后端服务地址输入框 (默认: http://user-web:4301)\n   - Kong 路由前缀输入框 (默认: /api)\n   - Strip Path 开关 (Toggle: Yes/No)\n   - 前端实际请求路径输入框 (默认: /api/user/signup)\n5. 行为与可视化展示:\n   - 实时计算 Kong 最终发往后端的 URL。\n   - 逻辑:如果前端请求路径以 Kong 路由前缀开头,且 Strip Path 为 Yes,则从前端请求中剔除该前缀后,拼接到后端服务地址上。如果为 No,则直接将前端请求路径拼接到后端服务地址上。如果不匹配前缀,提示路由匹配失败。\n   - 在结果区域,画出一条流量链路图:`Frontend [URL]` -> `Kong Gateway (Match: [Route Path], Strip: [Yes/No])` -> `Backend Service [Final URL]`。\n   - 动态高亮被剔除或保留的路径部分,清晰展示 URL 组装过程。\n   - 语言使用中文。","id":"im_10aa9a7d8ae0a97d"}}

kong部署到服务器,然后再配置个域名,这样任何人都可以访问,是否可以配置密码登录或者其他方式安全方式访问?

这是一个非常关键的安全意识!千万不要把毫无防护的 Kong 管理面板(Kong Manager)和 Admin API 暴露在公网上,否则任何扫描到你端口的人都可以进去随意篡改你的网关路由,这相当于把服务器的“大门钥匙”挂在了门把手上。

由于你目前使用的是 Kong 的开源免费版(Free 模式),它去掉了企业版自带的多用户登录(RBAC)界面。因此,Kong 本身不会提供输入账号密码的页面。

但这完全不是问题!既然你的架构中已经包含了 Nginx,最标准、最轻量级的做法就是利用 Nginx 在网关前面加一层“账号密码保护”(Basic Authentication)

以下是完整的配置步骤:

方案一:利用 Nginx 配置账号密码登录(推荐)

通过这种方式,当任何人访问你的域名时,浏览器会先弹出一个原生的输入框,只有输入正确的账号密码后,才能看到 Kong Manager 的界面。

第一步:生成密码文件

我们需要生成一个加密的密码文件(.htpasswd)给 Nginx 使用。因为你装了 Docker,最简单的生成方式是直接用一个临时的工具容器来生成,免去在宿主机安装命令的麻烦。

在你的服务器终端执行以下命令(将其中的 admin你的强密码 替换为你想要的账号和密码):

# 在你项目的 nginx 目录下生成一个 .htpasswd 文件
docker run --rm httpd:alpine htpasswd -bn admin 你的强密码 > ./nginx/.htpasswd

执行完后,你的 ./nginx/ 目录下会多出一个 .htpasswd 文件,里面存着加密后的密码。

第二步:配置 Nginx 反向代理

在你的 ./nginx/conf.d/ 目录下,新建一个专门给 Kong 管理台使用的配置文件,比如叫 kong-manager.conf

server {
    listen 80;
    # 填入你准备给 Kong 面板用的域名
    server_name kong.yourdomain.com; 

    # 强制跳转 HTTPS(强烈建议配置,防止密码被抓包泄露)
    # 如果你还没配 SSL,可以先把下面这段注释掉
    # return 301 https://$host$request_uri;

    location / {
        # 开启基础密码验证
        auth_basic "Restricted Access - Kong Manager";
        # 指向我们刚才生成的密码文件 (Nginx 容器内的路径)
        auth_basic_user_file /etc/nginx/.htpasswd;

        # 将通过密码验证的流量,转发给内部的 Kong Manager (8002 端口)
        proxy_pass http://kong-gateway:8002;
        
        # 传递标准头信息
        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;
    }
}

(注意:因为你的 Nginx 容器和 Kong 容器都在 infra-internal 这个内部网络里,所以 proxy_pass 可以直接写容器名 http://kong-gateway:8002,无需走公网。)

第三步:重启 Nginx 生效

让 Nginx 重新加载配置:

docker exec -it 你的nginx容器名 nginx -s reload

现在,当你在浏览器里输入 http://kong.yourdomain.com 时,就会弹出一个要求输入账号密码的提示框,安全性得到了极大的保障!


方案二:接入 Cloudflare Access (Zero Trust) —— 更现代的免密安全方案

如果你的域名碰巧托管在 Cloudflare 上,我强烈推荐你使用 Cloudflare Zero Trust(免费额度高达 50 个用户,绝对够用)。

  • 原理:不需要在 Nginx 里配密码。你在 Cloudflare 后台配置一条规则,拦截对 kong.yourdomain.com 的访问。
  • 体验:任何人访问域名,都会被重定向到 Cloudflare 的登录页。你可以设置只允许特定邮箱前缀的人访问,或者直接接入企业微信、钉钉、GitHub、Google 等扫码/授权登录。
  • 优势:这是目前业界最流行的“零信任”访问方案,你的源站服务器完全不需要对公网暴露端口,安全性比输入静态密码更高一层。

总结建议: 如果你追求快速搞定,用 Nginx Basic Auth(方案一) 最直接;如果你想要更现代、支持二次验证(2FA)的企业级体验,并且有 Cloudflare 账号,可以尝试 Cloudflare Access(方案二)

这份 Nginx 配置文件写得非常专业,不仅兼顾了 HTTP/HTTPS 双轨,还考虑到了 WebSocket 长链接和 AI 网关的长超时设置,可以直接用于生产环境。

我已经为你把 Nginx Basic Auth(基础账号密码验证) 补充进去了。为了最大程度保护你的管理面板,我将验证逻辑加在了 location / 块的顶部。

以下是补充完善后的配置文件:

# ==========================================
# kong.conf: kong 网关配置 (HTTP/HTTPS 双轨兼容版)
# ==========================================

server {
    # 👉 同时监听 HTTP 和 HTTPS,不做强制跳转 (完全符合你的要求)
    listen 80;
    listen 443 ssl;
    http2 on;

    server_name kong.einscat.com kong.einscat.local kong.einscat.ubuntu;

    # SSL 证书配置
    # ⚠️ 注意:如果你现在还没有生成证书,Nginx 会因为找不到文件而报错退出。
    # 如果你当前只想先用 HTTP 跑通测试,请务必先将下面这三行注释掉!
    ssl_certificate     /etc/nginx/ssl/kong.crt;
    ssl_certificate_key /etc/nginx/ssl/kong.key;
    include /etc/nginx/snippets/ssl_params.conf;

    access_log /var/log/nginx/kong_access.log main;
    error_log  /var/log/nginx/kong_error.log;

    # 设置 Docker 内部 DNS
    resolver 127.0.0.11 valid=30s;

    # 🌟 核心修复:直接使用 docker-compose 中定义的服务名 (service name),而不是容易变动的容器名
    set $kong_server "kong-gateway:8002";

    location / {
        # 👇 ================================================= 👇
        # 新增:Nginx Basic Auth 账号密码防护
        # 👇 ================================================= 👇
        auth_basic "Restricted Access - Kong Manager";
        auth_basic_user_file /etc/nginx/.htpasswd;
        
        proxy_pass http://$kong_server;

        # WebSocket 及 SSE 核心参数
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # 核心请求头注入
        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_set_header HTTPS $https_status;

        # AI 网关专属生产级调优
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 300s;
        proxy_connect_timeout 300s;
        proxy_send_timeout 300s;
    }
}

💡 记得执行最后两步让它生效:

1. 确保密码文件已经生成 如果你还没生成密码文件,请在宿主机执行这条命令(生成名为 admin 的账号和你的密码,文件会直接落入 ./nginx/ 目录供容器读取):

docker run --rm httpd:alpine htpasswd -bn admin 你的强密码 > ./nginx/.htpasswd

2. 重载 Nginx 配置 使最新的带有 Auth 验证的规则生效(假设你的 nginx 容器名为 app-nginx-gateway,请根据实际情况替换):

docker exec -it app-nginx-gateway nginx -s reload

关于 ./nginx/.htpasswd 的物理位置以及 Nginx 如何读取它,这涉及到 Docker 的**卷挂载(Volumes)**机制。

1.这个文件在宿主机的哪里?

当你执行这条命令时: docker run --rm httpd:alpine htpasswd -bn einscat 密码 > ./nginx/.htpasswd

  • 物理路径:它就在你当前执行脚本或命令的目录下,名为 nginx 的子文件夹里。
  • 绝对路径示例:如果你在 /home/user/my-project 下操作,那么文件的完整路径就是 /home/user/my-project/nginx/.htpasswd

2.Nginx 容器如何读取到它?

Nginx 容器本身是一个隔离的环境,它默认看不见宿主机上的文件。它能读取到这个文件,是因为你在 docker-compose.yaml 中配置了目录映射

请看你 03-gen-compose.sh 脚本中 nginx-proxy 服务的 volumes 部分:

volumes:
  # 这里的配置是将宿主机的 ./nginx 文件夹 映射到 容器内的 /etc/nginx 目录
  - ./nginx:/etc/nginx:ro 

映射逻辑拆解:

  • 左侧 ./nginx:指的是宿主机上的文件夹(包含你的 kong.conf 和刚刚生成的 .htpasswd)。
  • 右侧 /etc/nginx:指的是容器内部的路径。
  • 结果:当你把文件放到宿主机的 ./nginx/.htpasswd 时,在 Nginx 容器内部,这个文件的路径就变成了 /etc/nginx/.htpasswd

3.配置中的对应关系

在你提供的 kong.conf 配置中,有这样一行:

auth_basic_user_file /etc/nginx/.htpasswd;

这里的 /etc/nginx/.htpasswd容器内部路径

  • Nginx 进程启动后,它会去容器内的 /etc/nginx/ 目录下找 .htpasswd
  • 由于 Docker 的挂载机制,它实际上读取的是你宿主机 ./nginx/ 目录下的那个物理文件。

💡 验证方法

如果你想确认文件是否已经成功进入容器,可以执行以下命令:

# 查看容器内部是否存在该文件(假设容器名为 app-nginx-gateway)
docker exec -it app-nginx-gateway ls -la /etc/nginx/.htpasswd

如果命令返回了文件信息,说明挂载成功。如果提示 No such file,说明你的 docker-compose 挂载路径可能与实际存放文件的路径不一致。

总结

  1. 宿主机位置:当前项目目录下的 nginx/.htpasswd
  2. 读取方式:通过 Docker Compose 的 volumes 挂载,将宿主机目录映射到容器内的 /etc/nginx
  3. 引用方式:Nginx 配置文件中使用容器内路径 /etc/nginx/.htpasswd 进行引用。

这是一个非常严谨的架构设计思考!

答案是:完全可以独立命名,并且在生产环境中,强烈建议你为不同的服务(或不同的访问层级)创建独立的密码文件。

把所有密码都塞在一个 .htpasswd 文件里虽然省事,但如果未来你要收回某个人的权限,或者有新的服务接入,管理起来就会非常混乱。

下面我教你如何优雅地实现“分文件管理密码”。

1.生成独立的密码文件

我们依然使用那个临时的 httpd 容器,只不过这次我们在输出时,指定不同的文件名。

假设你要为 Kong 管理面板和未来可能的某个监控面板分别生成独立的密码:

为 Kong 生成专属密码文件:

docker run --rm httpd:alpine htpasswd -bn kong_admin 密码A > ./nginx/.htpasswd_kong

为其他服务(比如 Grafana 或测试环境)生成密码文件:

docker run --rm httpd:alpine htpasswd -bn monitor_user 密码B > ./nginx/.htpasswd_monitor

执行后,你的 ./nginx/ 目录下就会有两个清晰的文件:.htpasswd_kong.htpasswd_monitor

2.在 Nginx 配置中独立引用

既然文件拆分了,在 Nginx 的配置文件里,你只需要在不同的 serverlocation 块中,指向对应的文件即可。

以你之前的 Kong 配置为例:

server {
    listen 80;
    server_name kong.einscat.com;

    location / {
        auth_basic "Restricted Access - Kong Manager";
        # 👇 这里修改为专门给 Kong 用的密码文件
        auth_basic_user_file /etc/nginx/.htpasswd_kong;
        
        proxy_pass http://kong-gateway:8002;
        # ... 其他 proxy 配置 ...
    }
}

未来如果你有另一个服务(比如一个纯前端的内网工具):

你可以新建一个配置文件(比如 monitor.conf):

server {
    listen 80;
    server_name monitor.einscat.com;

    location / {
        auth_basic "Restricted Access - Monitor Tools";
        # 👇 这里指向监控专属的密码文件
        auth_basic_user_file /etc/nginx/.htpasswd_monitor;
        
        proxy_pass http://某个内部容器:8080;
    }
}

3.给同一个文件添加多个账号(补充知识)

如果你希望Kong 面板同时允许张三(zhangsan)和李四(lisi)访问,但他们用不同的密码,你可以继续往同一个文件里追加账号。

注意:追加账号时,需要使用 >>(追加),而不是 >(覆盖)。

# 第一步:创建文件并写入张三
docker run --rm httpd:alpine htpasswd -bn zhangsan 密码123 > ./nginx/.htpasswd_kong

# 第二步:往同一个文件里追加李四 (注意是 >>)
docker run --rm httpd:alpine htpasswd -bn lisi 密码456 >> ./nginx/.htpasswd_kong

这样,zhangsanlisi 都能访问 Kong 的域名,这在团队协作时非常有用!


我直接上传到nginx容器还是挂载文件,文件一定要htpasswd_kong这样命名吗?是否可以新建目录 htpasswd,密码文件为kong,挂载多个服务密码文件,如何挂载

这是一个非常优秀的架构洁癖!你完全抓住了精髓。

你的想法不仅可行,而且是生产环境中最标准、最推荐的最佳实践。下面我为你逐一解答,并教你如何优雅地实现它。

1.直接上传还是挂载文件?

绝对要使用挂载(Volumes)!千万不要直接上传到容器内。

Docker 容器是“阅后即焚”的(Ephemeral)。如果你直接把文件 docker cp 进容器,一旦容器重启、升级或者崩溃重建,密码文件就会立刻丢失。必须把文件放在宿主机,通过映射让容器读取,这样才能保证数据的持久化

2.名字必须是 .htpasswd_kong 吗?可以建独立目录吗?

完全不需要!名字随你定,建独立目录是非常棒的主意。

Nginx 根本不在乎这个文件叫什么名字,甚至不在乎它有没有后缀名。只要它是一个包含正确哈希密码的纯文本文件即可。

你设想的结构非常完美,我们可以这样设计宿主机的目录:

你的项目根目录/
└── nginx/
    ├── conf.d/
    │   └── kong.conf
    ├── html/
    └── htpasswd/          <-- 💡 新建的密码专用目录
        ├── kong           <-- Kong 的密码文件
        ├── grafana        <-- (未来) Grafana 的密码文件
        └── nacos          <-- (未来) Nacos 的密码文件

3.如何生成并挂载到多个服务?

最奇妙的地方在于:你完全不需要修改 docker-compose.yaml

回看你之前的编排脚本,你写了这样一行挂载: - ./nginx:/etc/nginx:ro 这句话的意思是:“把宿主机的整个 ./nginx 文件夹,原封不动地搬到容器里的 /etc/nginx”。

所以,只要你在宿主机的 ./nginx 下新建了 htpasswd 目录,它就自动被挂载到了容器里的 /etc/nginx/htpasswd,你不需要为每个密码文件单独写挂载语句!

实操步骤:

第一步:在宿主机建目录并生成密码文件 在你的项目根目录下执行:

# 1. 创建专门存放密码的目录
mkdir -p ./nginx/htpasswd

# 2. 为 Kong 生成专属密码文件(文件名为 kong)
docker run --rm httpd:alpine htpasswd -bn einscat 你的强密码 > ./nginx/htpasswd/kong

# 3. (可选) 为未来的其他服务生成密码文件(文件名为 monitor)
docker run --rm httpd:alpine htpasswd -bn monitor_user 密码B > ./nginx/htpasswd/monitor

第二步:在 Nginx 配置文件中优雅地引用它 打开你的 ./nginx/conf.d/kong.conf,将密码路径修改为你刚刚规划的新路径:

    location / {
        auth_basic "Restricted Access - Kong Manager";
        
        # 👇 路径变成了容器内的 /etc/nginx/htpasswd/kong
        auth_basic_user_file /etc/nginx/htpasswd/kong;
        
        proxy_pass http://$kong_server;
        # ... 保持其他配置不变 ...
    }

第三步:重载 Nginx 生效

docker exec -it app-nginx-gateway nginx -s reload

这样一来,所有的密码文件都整整齐齐地收纳在 htpasswd 目录中,没有后缀名的干扰,按服务名隔离,日后维护或交接给其他同事时,看一眼目录结构就能秒懂!


目前网关面板的安全已经搞定了,你打算把这个密码保护功能也应用到其他的内部面板(比如 Nacos 和 Jenkins)上,还是目前只针对 Kong 呢?

明白了,你使用的是**细粒度挂载(Fine-grained Mounts)**方式。这种方式在生产环境中非常严谨,因为它只允许容器访问特定的文件或目录,安全性更高。

既然你没有挂载整个 ./nginx 目录,那么容器内部的 /etc/nginx/ 文件夹下就不会自动出现你新建的 htpasswd 子目录。

要实现你设想的“独立目录管理密码”,你需要做以下两步调整:

第一步:03-gen-compose.sh 中增加挂载项

你需要在 nginx-proxy 服务的 volumes 列表中,显式地把宿主机的 htpasswd 目录挂载进去。

请在你的脚本中找到 Nginx 的 volumes 部分,添加下面高亮的那一行:

    volumes:
      # 替换默认主配置
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      # 挂载公用代码段
      - ./nginx/snippets:/etc/nginx/snippets:ro
      # 挂载子配置
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      # 👇 新增这一行:将密码目录挂载到容器内
      - ./nginx/htpasswd:/etc/nginx/htpasswd:ro
      
      - ./nginx/html:/var/www/html:ro
      - ./nginx/init-ssl.sh:/docker-entrypoint.d/99-init-ssl.sh:ro
      - ./nginx/ssl:/etc/nginx/ssl
      - ${PERSIST_DIR}/nginx/log:/var/log/nginx

第二步:kong.conf 中引用

因为你现在已经把 ./nginx/htpasswd 映射到了容器内的 /etc/nginx/htpasswd,你的 Nginx 配置文件 kong.conf 保持如下配置即可:

location / {
    auth_basic "Restricted Access - Kong Manager";
    # 容器会去 /etc/nginx/htpasswd/ 目录下找名为 kong 的文件
    auth_basic_user_file /etc/nginx/htpasswd/kong;
    
    proxy_pass http://$kong_server;
    # ... 其他配置 ...
}

💡 为什么细粒度挂载需要额外这一行?

理解 Docker 挂载的“映射关系”非常重要。当你没有挂载父目录(./nginx)时,子目录就像是一个个独立的岛屿。为了帮你直观理解这种映射逻辑,我准备了一个交互式工具,你可以对比“目录挂载”与“文件挂载”的区别。

{"component":"LlmGeneratedComponent","props":{"height":"600px","prompt":"创建一个 Docker 卷挂载(Volumes)映射可视化工具。\n\n1. 目标:演示‘目录挂载’与‘细粒度文件挂载’对容器内文件系统的不同影响。\n2. 初始状态:\n   - 宿主机结构:./nginx/ (包含 nginx.conf, conf.d/, htpasswd/)\n   - 模式选择:细粒度挂载 (Fine-grained)\n3. 交互逻辑:\n   - 提供一个切换开关:[全部挂载 ./nginx] vs [细粒度挂载单个子项]。\n   - 当选择 [细粒度挂载] 时,用户可以勾选:\n     - [x] nginx.conf\n     - [x] conf.d/\n     - [ ] htpasswd/\n4. 可视化表现:\n   - 左侧展示‘宿主机目录树’。\n   - 右侧展示‘容器内 /etc/nginx/ 目录树’。\n   - 使用连线或动画展示文件是如何从左侧‘投影’到右侧的。\n   - 如果用户未勾选 htpasswd/,右侧容器内部应显示该目录缺失,并标记为‘无法读取’。\n5. 教育意义:强调在没有挂载父目录的情况下,任何新增的宿主机子目录必须手动添加到 volumes 列表中,容器才能识别。\n6. 语言:中文。","id":"im_2d7cae9b2e84d0f2"}}

总结你的操作流程:

  1. 宿主机:创建 ./nginx/htpasswd/ 目录并生成名为 kong 的密码文件。
  2. 修改脚本:在 03-gen-compose.sh 的 Nginx volumes 中添加 - ./nginx/htpasswd:/etc/nginx/htpasswd:ro
  3. 重新生成并启动:执行脚本生成新的 docker-compose.yaml,然后运行 docker-compose up -d nginx-proxy 重建容器。

这样你的配置就既安全又整洁了!



这是一个非常经典且触及网关核心架构的问题。理解了这几个端口的含义和 HTTPS 的流向,你对 API 网关的掌控力就会上一个大台阶。

我们分两部分来彻底把这些概念理清。


一、解密 Kong 的四大核心端口

在 Kong 的架构设计中,端口被严格划分为**“数据面” (Data Plane)** 和 “控制面” (Control Plane)

1.数据面端口(业务流量入口,对外的“收费站”)

  • KONG_PROXY_HTTP_PORT=8000: 这是 Kong 的 HTTP 代理端口。所有外部系统想要访问你后端的微服务(比如 user-webeam-web),如果不加密,都要把请求发到这里。
  • KONG_PROXY_HTTPS_PORT=8443: 这是 Kong 的 HTTPS 代理端口。和 8000 一样,但它负责处理加密的业务流量。

2.控制面端口(管理流量入口,对内的“指挥中心”)

  • KONG_ADMIN_PORT=8001: 这是 Kong 的 Admin API(底层管理接口)。你往 Kong 里添加路由、配置插件等操作,底层其实都是在调用这个端口的 RESTful API。极其危险,绝不能对公网开放!
  • KONG_ADMIN_GUI_PORT=8002: 这就是我们之前配置的 Kong Manager 可视化管理面板。你在浏览器里点点点配置路由,其实就是这个面板的前端代码在偷偷帮你调用 8001 端口。

二、HTTPS 到底是谁在访问?(理清通信链路)

你问:“配置http后前端是https访问还是用户在浏览器通过https访问?”

答案是:这两者在网关眼里是一回事。 无论是用户在浏览器地址栏直接输入 https://...,还是前端代码(如 Vue/React)通过 Ajax/Axios 发起 https://... 的请求,它们都是客户端发起的 HTTPS 请求

在微服务架构中,HTTPS 的标准处理流程(称为 SSL 终结 / SSL Termination)通常是这样的:

你的当前架构链路:

因为你在 Kong 前面挡了一层 Nginx,所以整个流量链路是这样的:

  1. 用户浏览器 / 前端代码 发起请求 https://api.einscat.com/user/signup
  2. 请求首先到达最外层的 Nginx (监听 443 端口)
  3. Nginx 负责“解密”(使用你配置的 SSL 证书,把 HTTPS 拆解成 HTTP)。
  4. Nginx 将解密后的 HTTP 流量,通过内网转发给 Kong 的 8000 端口
  5. Kong 根据路由规则,将请求转发给后端的 user-web:4301

结论: 因为有了 Nginx 在前面扛着 HTTPS 加解密的脏活累活,你的 Kong 甚至都不需要配置 HTTPS,它只需要安安心心在内网监听 8000 端口接收 HTTP 流量即可。 前端依然是用 https:// 来访问,只是加密过程在 Nginx 这一层就结束了。


三、如何配置 HTTPS?

结合你目前的架构,你有两种方式来实现 HTTPS,强烈推荐方案一

方案一:在 Nginx 层配置 HTTPS(推荐,你已经做了一大半了)

我们在上一轮沟通的 kong.conf (Nginx 配置文件) 中,其实已经为你写好了 HTTPS 的框架:

server {
    listen 80;
    listen 443 ssl; # 👈 Nginx 监听 HTTPS
    server_name kong.einscat.com;

    # 👇 1. 你只需要把申请好的域名证书放到这对应目录下
    ssl_certificate_key /etc/nginx/ssl/kong.key;
    # include /etc/nginx/snippets/ssl_params.conf;

    location / {
        # 👇 2. Nginx 解密后,把流量通过 HTTP 传给后端的 Kong
        proxy_pass http://kong-gateway:8000; # (如果是业务路由指向8000,管理面板指向8002)
    }
}

操作步骤:

  1. 去阿里云/腾讯云免费申请一个你域名的 SSL 证书。
  2. 下载 Nginx 格式的证书,改名为 kong.crt (公钥) 和 kong.key (私钥)。
  3. 把这两个文件放到宿主机的 ./nginx/ssl/ 目录下。
  4. 重启 Nginx:docker exec -it app-nginx-gateway nginx -s reload。 前端直接访问 https://kong.einscat.com 即可畅通无阻!

方案二:在 Kong 层配置 HTTPS(如果不用 Nginx)

如果你未来把最外层的 Nginx 撤掉了,想让 Kong 直接面对公网扛 HTTPS,你可以:

  1. 登录 Kong Manager (8002 面板)。
  2. 在左侧菜单找到 Certificates
  3. 点击右上角 New Certificate,把你申请的 SSL 证书内容(CRT 和 KEY 的文本内容)直接粘贴进去并保存。
  4. 在配置 Route 时,确保 Protocols 勾选了 https
  5. 此时,前端就需要通过访问 Kong 的 8443 端口(或者你在 .env 里把它映射到宿主机的 443)来进行 HTTPS 通信了。

总结来说,网关架构中最优雅的做法就是:外网到 Nginx 走 HTTPS,Nginx 到 Kong 走 HTTP,Kong 到微服务走 HTTP。 这样既保证了公网传输安全,又降低了内网服务解密 HTTPS 的性能损耗。


alt text

alt text

alt text