Lura v2.14.1 Docker Compose 部署指南

用 KrakenD CE 2.13.11 官方交付物(内嵌 Lura v2.14.x 引擎)在 Docker Compose 中编排 API 网关与两个演示后端,覆盖部署、验证、生命周期与升级。

LuraDockerDocker ComposeUbuntuUbuntu 22.04LinuxLuraKrakenDAPI 网关2026/10/17

Lura v2.14.1 Docker Compose 部署指南

目标:用 KrakenD CE 官方交付物(内嵌 Lura v2.14.x 引擎)在 Docker Compose 中编排 API 网关与两个演示后端,覆盖部署、验证、日常运维、升级与卸载全流程。已在 Ubuntu 22.04 实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS
  • 容器环境:Docker 29.8.1、Compose 插件 v2.40.2
  • 网关镜像:krakend:2.13.11(内嵌 Lura v2.14.x 引擎)
  • 演示后端:product-api(python:3.11-alpine,容器内端口 8000,产品数据)、stock-api(python:3.11-alpine,容器内端口 8001,库存数据)
  • 端口:网关对外 8080
  • 配置文件路径:宿主机 /opt/lura-compose/krakend/krakend.json(只读挂载为容器内 /etc/krakend/krakend.json)、后端脚本 /opt/lura-compose/backend/mock_backend.py

二、先说清形态:Compose 里跑的是哪个"Lura"

Lura 框架本身只发布 Go 源码 tag,没有官方交付镜像。以编排方式部署 Lura 引擎,实际使用的就是 KrakenD CE 官方交付物:krakend:2.13.11 这个 Docker Hub 官方镜像内嵌的引擎正是 Lura v2.14.x(KrakenD CE 2.13.11 的 go.mod 依赖 github.com/luraproject/lura/v2 v2.14 系列)。本文全部命令在 Ubuntu 22.04.5 LTS 上实测,Compose 插件版本 v2.40.2、Docker 版本 29.8.1。

部署拓扑一共三个服务:

客户端 ──► gateway (krakend:2.13.11, 端口 8080)
              ├──► product-api (python:3.11-alpine, 内部 8000,产品数据)
              └──► stock-api    (python:3.11-alpine, 内部 8001,库存数据)

网关把两个后端聚合为一个端点 /api/products/{id}:一次请求同时返回产品与库存。

💡 技术拓展:想在编排环境里跑"裸 Lura"?两条路:一是参照《Lura v2.14.1 Ubuntu 22.04 安装指南》自行编译二进制后写 Dockerfile 打包;二是继续用 KrakenD CE 交付物——它就是官方维护的 Lura 发行版,除自定义引擎参数外能力一致。绝大多数场景推荐后者。

三、准备部署文件

3.1 目录结构

root@ubuntu22:~# mkdir -p /opt/lura-compose/krakend /opt/lura-compose/backend
root@ubuntu22:~# cd /opt/lura-compose
root@ubuntu22:/opt/lura-compose# touch docker-compose.yml krakend/krakend.json backend/mock_backend.py
root@ubuntu22:/opt/lura-compose# ls -R .
.:
backend  docker-compose.yml  krakend

./backend:
mock_backend.py

./krakend:
krakend.json

3.2 演示后端 mock_backend.py

两个后端共用同一脚本,靠启动参数区分角色(backend-a 产品、backend-b 库存):

root@ubuntu22:/opt/lura-compose# cat > backend/mock_backend.py << 'EOF'
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import json, sys

PORT = int(sys.argv[1])
NAME = sys.argv[2]

DATA = {
    "backend-a": {
        "/products/1": {"id": 1, "name": "Widget", "price": 9.99, "currency": "USD"},
        "/products/2": {"id": 2, "name": "Gadget", "price": 24.50, "currency": "USD"},
    },
    "backend-b": {
        "/stock/1": {"product_id": 1, "in_stock": True, "qty": 42},
        "/stock/2": {"product_id": 2, "in_stock": False, "qty": 0},
    },
}

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        body = DATA.get(NAME, {}).get(self.path)
        if body is None:
            self.send_response(404)
            self.send_header("Content-Type", "application/json")
            self.end_headers()
            self.wfile.write(json.dumps({"error": "not found", "path": self.path}).encode())
            return
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(json.dumps(body).encode())
    def log_message(self, *a):
        pass

ThreadingHTTPServer(("0.0.0.0", PORT), Handler).serve_forever()
EOF

3.3 网关配置 krakend.json

root@ubuntu22:/opt/lura-compose# cat > krakend/krakend.json << 'EOF'
{
  "version": 3,
  "name": "Lura Compose Gateway",
  "port": 8080,
  "cache_ttl": "60s",
  "timeout": "3s",
  "extra_config": {
    "telemetry/logging": {
      "level": "INFO",
      "prefix": "[KRAKEND]",
      "syslog": false,
      "stdout": true
    }
  },
  "endpoints": [
    {
      "endpoint": "/api/products/{id}",
      "method": "GET",
      "backend": [
        {
          "host": ["http://product-api:8000"],
          "url_pattern": "/products/{id}",
          "group": "product"
        },
        {
          "host": ["http://stock-api:8001"],
          "url_pattern": "/stock/{id}",
          "group": "stock"
        }
      ]
    },
    {
      "endpoint": "/healthz",
      "method": "GET",
      "output_encoding": "no-op",
      "backend": [
        {
          "host": ["http://product-api:8000"],
          "url_pattern": "/products/1",
          "encoding": "no-op"
        }
      ]
    }
  ]
}
EOF

两个要点:host 用的是服务名 product-api/stock-api(Compose 网络内置 DNS 解析服务名);/healthz 用 no-op 编码透传上游原始响应。

⚠️ 排障实录:端点名不要以 __ 开头。实测把健康端点命名为 /__health 时网关反复重启,日志报 ignoring the '/__health' endpoint, since it is invalid!!!——双下划线前缀是 KrakenD/Lura 内部端点保留字。改名为 /healthz 后正常。

3.4 docker-compose.yml

root@ubuntu22:/opt/lura-compose# cat > docker-compose.yml << 'EOF'
services:
  gateway:
    image: krakend:2.13.11
    container_name: lura-gateway
    ports:
      - "8080:8080"
    volumes:
      - ./krakend/krakend.json:/etc/krakend/krakend.json:ro
    depends_on:
      - product-api
      - stock-api
    restart: unless-stopped

  product-api:
    image: python:3.11-alpine
    container_name: lura-product-api
    hostname: product-api
    volumes:
      - ./backend/mock_backend.py:/srv/mock_backend.py:ro
    command: python /srv/mock_backend.py 8000 backend-a
    restart: unless-stopped

  stock-api:
    image: python:3.11-alpine
    container_name: lura-stock-api
    hostname: stock-api
    volumes:
      - ./backend/mock_backend.py:/srv/mock_backend.py:ro
    command: python /srv/mock_backend.py 8001 backend-b
    restart: unless-stopped
EOF

说明:镜像 krakend:2.13.11 的默认启动命令就是 krakend run -c /etc/krakend/krakend.json,所以 gateway 服务不用写 command;配置文件以只读方式挂载进固定路径。

四、启动与验证

4.1 拉起编排

root@ubuntu22:/opt/lura-compose# docker compose up -d
[+] Running 4/4
 ✔ Network lura-compose_default    Created
 ✔ Container lura-product-api      Started
 ✔ Container lura-stock-api        Started
 ✔ Container lura-gateway          Started

4.2 查看运行状态

root@ubuntu22:/opt/lura-compose# docker compose ps
NAME               IMAGE                COMMAND                  SERVICE       CREATED         STATUS         PORTS
lura-gateway       krakend:2.13.11      "docker-entrypoint.s…"   gateway       4 minutes ago   Up 4 minutes   0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp, 8090/tcp
lura-product-api   python:3.11-alpine   "python /srv/mock_ba…"   product-api   4 minutes ago   Up 4 minutes
lura-stock-api     python:3.11-alpine   "python /srv/mock_ba…"   stock-api     4 minutes ago   Up 4 minutes

4.3 验证聚合端点与健康端点

root@ubuntu22:/opt/lura-compose# curl -s http://127.0.0.1:8080/api/products/1
{"product":{"currency":"USD","id":1,"name":"Widget","price":9.99},"stock":{"in_stock":true,"product_id":1,"qty":42}}
root@ubuntu22:/opt/lura-compose# curl -s http://127.0.0.1:8080/api/products/2
{"product":{"currency":"USD","id":2,"name":"Gadget","price":24.5},"stock":{"in_stock":false,"product_id":2,"qty":0}}
root@ubuntu22:/opt/lura-compose# curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/healthz
200

/api/products/1 一次请求拿到了 product 与 stock 两组数据——这正是 Lura 代理层的并发聚合能力。

4.4 确认引擎版本

root@ubuntu22:/opt/lura-compose# docker exec lura-gateway krakend version
KrakenD Version: 2.13.11
Go Version: 1.26.8
Glibc Version: MUSL-1.2.5_(alpine-3.23.5)

五、日常运维命令

5.1 日志查看

root@ubuntu22:/opt/lura-compose# docker compose logs gateway --tail 5
lura-gateway  | [KRAKEND] 2026/10/17 - 04:03:20.???  INFO [SERVICE: Executor] [...]
lura-gateway  | [GIN] ... | 200 | ... | GET "/api/products/1"

docker compose logs -f gateway 可持续跟踪;telemetry/logging 配置里 stdout: true 决定日志是否进标准输出。

5.2 修改配置后生效

网关只在启动时读配置,改完 krakend/krakend.json 后重启 gateway 服务:

root@ubuntu22:/opt/lura-compose# docker compose restart gateway
 Container lura-gateway  Stopping
 Container lura-gateway  Started
root@ubuntu22:/opt/lura-compose# docker compose ps gateway
NAME               IMAGE                COMMAND                  SERVICE       CREATED         STATUS         PORTS
lura-gateway       krakend:2.13.11      "docker-entrypoint.s…"   gateway       5 minutes ago   Up 6 seconds   0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp, 8090/tcp

5.3 停止与销毁

root@ubuntu22:/opt/lura-compose# docker compose down
 Container lura-gateway        Removed
 Container lura-stock-api      Removed
 Container lura-product-api    Removed
 Network lura-compose_default  Removing
 Network lura-compose_default  Removed

再次 docker compose up -d 即完整重建。实测销毁重建后聚合端点依然正常:

root@ubuntu22:/opt/lura-compose# docker compose up -d
 Container lura-product-api Started
 Container lura-gateway Starting
 Container lura-gateway Started
root@ubuntu22:/opt/lura-compose# curl -s http://127.0.0.1:8080/api/products/2
{"product":{"currency":"USD","id":2,"name":"Gadget","price":24.5},"stock":{"in_stock":false,"product_id":2,"qty":0}}

5.4 配置文件校验

改配置后先跑一遍语法校验再重启,可以避免网关起不来:

root@ubuntu22:/opt/lura-compose# docker compose config --quiet && echo "compose config OK"
compose config OK
root@ubuntu22:/opt/lura-compose# docker exec lura-gateway krakend check -c /etc/krakend/krakend.json
Parsing configuration file: /etc/krakend/krakend.json
Syntax OK!

⚠️ 排障实录:docker compose ps 里 gateway 状态反复 Restarting,用 docker compose logs gateway | tail -5 看原因。实测遇到的两类:一是 __ 前缀端点被拒(见 3.3 节排障),二是配置 JSON 语法错误导致 krakend run 启动即退出,restart: unless-stopped 会不断拉起又退出。

六、升级到新版本

KrakenD CE 2.x 系列内嵌 Lura v2.14.x 引擎,升级编排只需换镜像 tag。以升到 v3 系列首版为例(v3 内嵌 Lura v3.0.0 引擎,配置格式有变更,升级前务必读官方迁移说明):

root@ubuntu22:/opt/lura-compose# sed -i 's/krakend:2.13.11/krakend:3.0.0/' docker-compose.yml
root@ubuntu22:/opt/lura-compose# docker compose up -d

先在测试环境验证配置兼容性再操作生产。回退同样改 tag 后 docker compose up -d。

💡 技术拓展:版本对应关系(实测核实)——KrakenD CE 2.13.x ↔ Lura v2.14.x;KrakenD CE 3.0.x ↔ Lura v3.0.0。选镜像 tag 时看 KrakenD 版本即可,它就是 Lura 引擎的发行号。固定 tag(如 krakend:2.13.11)而不是 latest,保证多环境一致性。

七、卸载

root@ubuntu22:/opt/lura-compose# docker compose down
root@ubuntu22:/opt/lura-compose# docker rmi krakend:2.13.11 python:3.11-alpine
root@ubuntu22:/opt/lura-compose# cd /opt && rm -rf lura-compose

如需保留配置文件模板,只删除服务与网络,跳过 rm -rf 即可。

八、参考链接