# 云测试用作发布目标时的 compose 叠加片段(project: weknora-test-v071) # # 作用:把"唯一入口"这个不变量在云测试上真正建立起来,让维护窗口有可信的排空证据。 # 1. app 不再发布宿主机端口(写入者发布端口 = 存在绕开闸门的直连通道,拓扑校验会拒绝); # 2. 新增 ingress 闸门,成为宿主机 8080 上唯一的 HTTP 入口,并在 SIGTERM 时写 drain.json; # 3. frontend 的 API 目标改为 ingress(这样网页流量也走闸门,关闸门 = 站点真的关)。 # # 使用(父执行,先校验再应用): # docker compose -f compose.yaml -f compose.release-overlay.yaml config >/dev/null # docker compose -f compose.yaml -f compose.release-overlay.yaml up -d app ingress frontend # # !reset 需要 Docker Compose >= 2.24(云端实测 2.40.3)。 # # 网络:本项目实际网络名是 weknora-test-v071-network(不是 compose 默认的 *_default)。 # 网络:本项目实际网络名是 weknora-test-v071-network(不是 compose 默认的 *_default)。 # ingress 用独立 key `release_target` 以 external 方式加入它:既不重定义原 default, # 也不靠"默认网络恰好同名"这种巧合。 name: weknora-test-v071 services: app: # 写入者不发布端口;验证器/发布执行器的直连走 docker 网络里的服务名 app:8080。 ports: !reset [] ingress: # 唯一对外入口:关入口=停这个闸门。镜像只用现成的 python,不构建、不改 WeKnora 镜像。 image: python:3.13-slim container_name: kgtest-ingress # restart: "no" 是硬约束:维护窗口把入口停下之后,Docker 不允许自己把它拉回来。 restart: "no" command: ["python3", "/gate/gate.py"] environment: # 闸门监听端口 = 宿主机发布端口,入口 URL 用同端口,拓扑校验才可比对。 GATE_PORT: "8080" GATE_UPSTREAM_HOST: app GATE_UPSTREAM_PORT: "8080" GATE_DRAIN_FILE: /gate-state/drain.json GATE_DRAIN_TIMEOUT: "45" ports: - "127.0.0.1:8080:8080" volumes: # gate.py 与 state 都在宿主机固定目录;发布执行器挂同一个 state 目录, # 所以"删除 drain 记录 / 读回排空证据"发生在同一个真实文件上。 - /srv/kgtest-gate/gate.py:/gate/gate.py:ro - /srv/kgtest-gate/state:/gate-state healthcheck: test: ["CMD", "python3", "-c", "import socket;s=socket.create_connection(('127.0.0.1',8080),2);s.close()"] interval: 3s timeout: 3s retries: 30 start_period: 5s stop_grace_period: 60s # 用独立 key 指向项目真实网络(external,不改原 compose 的 default 定义): # 这样 ingress 与 app 在同一条网络里能按服务名互通,也不会凭空创建 *_default。 networks: - release_target frontend: environment: # 网页的 /api 也要经过闸门,否则"关入口"只关了一半。 APP_HOST: ingress networks: release_target: external: true name: weknora-test-v071-network