Docker 部署 Kong云原生API網關
本指南提供了在 Docker Compose 上配置 Kong Gateway 的步驟,基于有數據庫模式的配置。本指南中使用的數據庫是 PostgreSQL。
前置條件
準備一臺Ubuntu服務器:
- 節點IP: 192.168.73.11
- 操作系統: Ubuntu 24.04
- 已安裝docker及docker-compose
部署kong網關
創建docker-compose文件
root@user-service:/data/apps/kong# cat docker-compose.yaml
name: 'kong-gateway'services:kong-db:image: postgres:17.5container_name: kong-dbrestart: alwaysenvironment:POSTGRES_DB: kongPOSTGRES_USER: kongPOSTGRES_PASSWORD: kongpassvolumes:- kong_db_data:/var/lib/postgresql/datanetworks:- kong-nethealthcheck:test: ["CMD-SHELL", "pg_isready -U kong -d kong"]interval: 10stimeout: 5sretries: 5kong-migrations:image: kong:3.9.1container_name: kong-migrationsdepends_on:kong-db:condition: service_healthyenvironment:KONG_DATABASE: postgresKONG_PG_HOST: kong-dbKONG_PG_USER: kongKONG_PG_PASSWORD: kongpasscommand: "kong migrations bootstrap"networks:- kong-netrestart: on-failurekong:image: kong:3.9.1container_name: kong-gatewayrestart: alwaysdepends_on:kong-migrations:condition: service_completed_successfullyenvironment:# kong databaseKONG_DATABASE: postgresKONG_PG_HOST: kong-dbKONG_PG_DATABASE: kongKONG_PG_USER: kongKONG_PG_PASSWORD: kongpass# kong proxyKONG_PROXY_LISTEN: 0.0.0.0:8000KONG_PROXY_LISTEN_SSL: 0.0.0.0:8443# kong adminKONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl# kong managerKONG_ADMIN_GUI_LISTEN: 0.0.0.0:8002, 0.0.0.0:8445 ssl# kong logsKONG_PROXY_ACCESS_LOG: /dev/stdoutKONG_PROXY_ERROR_LOG: /dev/stderrKONG_ADMIN_ACCESS_LOG: /dev/stdoutKONG_ADMIN_ERROR_LOG: /dev/stderrports:- "8000:8000" # Proxy- "8443:8443" # Proxy SSL- "8001:8001" # Admin API- "8444:8444" # Admin API SSL- "8002:8002" # Kong Manager- "8445:8445" # Kong Manager SSLnetworks:- kong-nethealthcheck:test: ["CMD-SHELL", "kong health"]interval: 15stimeout: 10sretries: 3networks:kong-net:driver: bridgevolumes:kong_db_data:driver: local
啟動服務
docker compose up -d
確認容器啟動狀態
root@user-service:/data/apps/kong# docker compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
kong-db postgres:17.5 "docker-entrypoint.s…" kong-db 3 days ago Up 3 days (healthy) 5432/tcp
kong-gateway kong:3.9.1 "/docker-entrypoint.…" kong 24 minutes ago Up 24 minutes (healthy) 0.0.0.0:8000-8002->8000-8002/tcp, [::]:8000-8002->8000-8002/tcp, 0.0.0.0:8443-8445->8443-8445/tcp, [::]:8443-8445->8443-8445/tcp
kong-migrations kong:3.9.1 "/docker-entrypoint.…" kong-migrations 3 days ago Exited (0) 24 minutes ago
root@user-service:/data/apps/kong#
瀏覽器訪問kong manager GUI
部署示例應用
下面是一個簡單且貼近實際業務場景的系統,模擬一個訂單系統的調用流程,基于docker構建:
- A 是前端頁面,用戶點擊“創建訂單”按鈕;
- A 通過 Kong 網關調用后端 B(訂單服務);
- B 接收到請求后,再通過 Kong 網關調用后端 C(庫存服務)進行扣減庫存;
- 最后返回響應到前端。
Kong 網關地址為:http://192.168.73.11:8000
創建相關目錄
mkdir -p /data/app/order-app{order-ui,order-servcie,inventory-service}
cd /data/app/order-app
1. 后端 C:庫存服務(inventory-service)
inventory-service/app.py
root@ubuntu:~# cat /data/app/order-app/inventory-service/app.py
from flask import Flask, jsonifyapp = Flask(__name__)@app.route("/inventory/decrease", methods=["POST"])
def decrease_inventory():print("庫存扣減成功")return jsonify({"msg": "庫存扣減成功"}), 200if __name__ == "__main__":app.run(host="0.0.0.0", port=5002)
inventory-service/Dockerfile
root@ubuntu:~# cat /data/app/order-app/inventory-service/Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY app.py .
RUN pip install flask
EXPOSE 5002
CMD ["python", "app.py"]
2. 后端 B:訂單服務(order-service)
order-service/app.py
root@ubuntu:~# cat /data/app/order-app/order-service/app.py
from flask import Flask, jsonify
import requestsapp = Flask(__name__)@app.route("/order/create", methods=["POST"])
def create_order():print("收到創建訂單請求,調用庫存服務扣減庫存")try:# 通過Kong調用庫存服務resp = requests.post("http://192.168.73.11:8000/inventory/decrease")return jsonify({"msg": "訂單創建成功", "inventory_response": resp.json()})except Exception as e:return jsonify({"msg": "訂單創建失敗", "error": str(e)}), 500if __name__ == "__main__":app.run(host="0.0.0.0", port=5001)
order-service/Dockerfile
root@ubuntu:~# cat /data/app/order-app/order-service/Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY app.py .
RUN pip install flask requests
EXPOSE 5001
CMD ["python", "app.py"]
3. 前端 A:訂單創建頁面
order-ui/index.html
root@ubuntu:~# cat /data/app/order-app/order-ui/index.html
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>訂單系統</title>
</head>
<body><h1>訂單系統</h1><button onclick="createOrder()">創建訂單</button><pre id="result"></pre><script>function createOrder() {fetch('http://192.168.73.11:8000/order/create', { method: 'POST' }).then(async res => {const text = await res.text();try {const json = JSON.parse(text);document.getElementById("result").innerText = JSON.stringify(json, null, 2);} catch (err) {console.error("非 JSON 響應內容:", text); // 只打印在控制臺document.getElementById("result").innerText = "請求失敗:服務暫時不可用,請稍后再試。";}}).catch(err => {console.error("請求錯誤:", err);document.getElementById("result").innerText = "網絡異常或服務器未響應,請檢查后端服務狀態。";});}</script></body>
</html>
order-ui/Dockerfile
root@ubuntu:~# cat /data/app/order-app/order-ui/Dockerfile
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
4. Docker Compose
構建docker鏡像
root@ubuntu:~# cd /data/app/order-app/order-ui
docker build -t registry.cn-shenzhen.aliyuncs.com/cnmirror/order-ui:v1.0 .
root@ubuntu:~# cd /data/app/order-app/order-service
docker build -t registry.cn-shenzhen.aliyuncs.com/cnmirror/order-service:v1.0 .
root@ubuntu:~# cd /data/app/order-app/order-service
docker build -t registry.cn-shenzhen.aliyuncs.com/cnmirror/inventory-service:v1.0 .
創建docker-compose
root@ubuntu:~# cat /data/app/order-app/docker-compose.yaml
name: "order-app"
services:ui:image: registry.cn-shenzhen.aliyuncs.com/cnmirror/order-ui:v1.0container_name: order-uiports:- "8080:80"networks:- order-netorder-service:image: registry.cn-shenzhen.aliyuncs.com/cnmirror/order-service:v1.0container_name: order-serviceports:- "5001:5001"networks:- order-netinventory-service:image: registry.cn-shenzhen.aliyuncs.com/cnmirror/inventory-service:v1.0container_name: inventory-serviceports:- "5002:5002"networks:- order-netnetworks:order-net:driver: bridge
啟動服務
docker compose up -d
確認容器啟動狀態
root@ubuntu:~# cd /data/app/order-app/
root@ubuntu:/data/app/order-app# docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
inventory-service registry.cn-shenzhen.aliyuncs.com/cnmirror/inventory-service:v1.0 "python app.py" inventory-service 19 seconds ago Up 18 seconds 0.0.0.0:5002->5002/tcp, [::]:5002->5002/tcp
order-service registry.cn-shenzhen.aliyuncs.com/cnmirror/order-service:v1.0 "python app.py" order-service 19 seconds ago Up 18 seconds 0.0.0.0:5001->5001/tcp, [::]:5001->5001/tcp
order-ui registry.cn-shenzhen.aliyuncs.com/cnmirror/order-ui:v1.0 "/docker-entrypoint.…" order-ui 19 seconds ago Up 3 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp
Kong配置建議(注冊B和C)
創建 Service(服務)
服務代表你后端的 API 服務,告訴 Kong 請求最終要發到哪里。
# 注冊服務B(訂單)
curl -i -X POST http://192.168.73.11:8001/services \--data name=order-service \--data url=http://192.168.73.11:5001# 注冊服務C(庫存)
curl -i -X POST http://192.168.73.11:8001/services \--data name=inventory-service \--data url=http://192.168.73.11:5002
查看注冊的服務
創建 Route(路由)
路由是入口規則,告訴 Kong 哪些路徑/域名/方法應該映射到哪個 Service。
# order-service 的路由(例如 /order)
curl -i -X POST http://192.168.73.11:8001/services/order-service/routes \--data name=order-route \--data paths[]=/order \--data 'strip_path=false'# inventory-service 的路由(例如 /inventory)
curl -i -X POST http://192.168.73.11:8001/services/inventory-service/routes \--data name=inventory-route \--data paths[]=/inventory \--data 'strip_path=false'
查看注冊的路由
全局啟用cores插件,解決跨域問題
curl -i -X POST http://192.168.73.11:8001/plugins \--data "name=cors" \--data "config.origins=*" \--data "config.methods[]=GET" \--data "config.methods[]=POST" \--data "config.methods[]=PUT" \--data "config.methods[]=DELETE" \--data "config.methods[]=OPTIONS" \--data "config.headers[]=Accept" \--data "config.headers[]=Authorization" \--data "config.headers[]=Content-Type" \--data "config.exposed_headers[]=X-Custom-Header" \--data "config.credentials=true" \--data "config.max_age=3600"
演示應用請求調用
演示流程:
- 啟動服務和Kong;
- 注冊 B 和 C 到 Kong;
- 瀏覽器訪問
http://192.168.73.11:8080
; - 點擊“創建訂單”;
- 查看鏈路:A → B → C。
驗證inventory-service接口
root@user-service:~# curl -s -X POST http://192.168.73.11:5002/inventory/decrease | jq
{"msg": "庫存扣減成功"
}
驗證order-service接口
root@user-service:~# curl -s -X POST http://192.168.73.11:5001/order/create | jq
{"inventory_response": {"msg": "庫存扣減成功"},"msg": "訂單創建成功"
}
驗證通過kong網關請求inventory-service接口
root@user-service:~# curl -s -X POST http://192.168.73.11:8000/inventory/decrease | jq
{"msg": "庫存扣減成功"
}
驗證通過kong網關請求order-service接口
root@user-service:~# curl -s -X POST http://192.168.73.11:8000/order/create | jq
{"inventory_response": {"msg": "庫存扣減成功"},"msg": "訂單創建成功"
}
瀏覽器輸出