新闻详情

新闻详情

首页 / 资讯中心 / 详情

ZITADEL v4 单节点 Docker Compose 部署:服务架构、TLS 覆盖层组合与 Traefik 路由不变量

发布时间:2026/9/14 10:08:25来源:尧图网络
ZITADEL v4 单节点 Docker Compose 部署:服务架构、TLS 覆盖层组合与 Traefik 路由不变量
ZITADEL v4 单节点 Docker Compose 部署服务架构、TLS 覆盖层组合与 Traefik 路由不变量【免费下载链接】zitadelZITADEL - Identity infrastructure, simplified for you.项目地址: https://gitcode.com/GitHub_Trending/zi/zitadel本文围绕仓库中deploy/compose目录的 AI 协作指令文档 AGENTS.md 展开系统讲解 ZITADEL 官方提供的生产级单节点 Docker Compose 部署方案四个核心服务与两个可选 profile 服务的组合方式、四种 Traefik TLS 模式的独立可组合性、基于h2c的 gRPC/REST 统一路由模型以及一套保证路由正确性的 CI 冒烟测试流水线。读完后你将理解该部署栈中每个 Compose 文件的职责边界、必须遵守的部署不变量external domain/port/secure 三件套一致性并能直接使用仓库给出的命令启动、校验和测试整套栈。一、部署栈总览四个核心服务 两个可选服务AGENTS.md 对该目录的定位非常明确这是一套production-aware的单节点 Docker Compose 部署。整套栈由以下服务构成类型服务说明核心zitadel-apiGo API 服务监听容器内 8080核心zitadel-loginNext.js 登录 UI监听容器内 3000核心postgres数据持久化核心proxyTraefik 反向代理发布 80/443可选redis通过cacheprofile 启用可选otel-collector通过observabilityprofile 启用流量走向可以从 README.md 的架构图直接看出所有浏览器流量先经过 Traefik80/443再按路由规则分发到zitadel-login登录 UI或zitadel-apiAPI/协议端点API 再访问 PostgreSQL┌─────────────────────────┐ Browser ──► │ Traefik (proxy) │ │ Port 80 / 443 │ └───┬──────────┬──────────┘ │ │ ┌──────────▼──┐ ┌───▼──────────┐ │ zitadel-api │ │ zitadel-login │ │ Go :8080 │ │ Next.js :3000 │ └──────┬───────┘ └──────────────┘ │ ┌──────▼───────┐ │ PostgreSQL │ └──────────────┘两个关键架构决策直接体现在 docker-compose.yml 中Login 与 API 分离部署。zitadel-login是独立的 Next.js 进程ghcr.io/zitadel/zitadel-login:${ZITADEL_VERSION}通过ZITADEL_API_URL: http://zitadel-api:8080在服务端直连 API而不是经浏览器跨域访问。它同时挂载zitadel-bootstrap卷只读以读取 bootstrap PAT。健康检查驱动的启动顺序。postgres就绪 →zitadel-api健康/app/zitadel ready探针→zitadel-login健康/ui/v2/login/healthy探针→proxy最后启动全部通过depends_on.condition: service_healthy串联见 docker-compose.yml 与 L83-L85。redis与otel-collector均声明在profiles之下L205-L228不显式启用 profile 时不会影响默认栈——这是文档明确列出的不变量之一。二、文件结构与职责边界AGENTS.md 第 2 节给出一张文件约定表README.md 对其有相同口径的补充。两者合并后的完整文件职责如下文件用途修改安全性docker-compose.yml基础栈——所有模式都从它起步必须能单独配合.env.example工作可以但需谨慎docker-compose.mode-letsencrypt.ymlTLS 覆盖层ACME HTTP challenge自带letsencrypt卷可以docker-compose.mode-external-tls.ymlTLS 覆盖层上游负载均衡器终结 TLS启用转发头信任可以docker-compose.mode-local-tls.ymlTLS 覆盖层自签证书挂载./certs/与traefik-local-tls.yml可以docker-compose.prodlike.ymlinit/setup/start 三段拆分覆盖层使用 YAML 锚点共享 DB 环境可以docker-compose.test.ymlCI 测试覆盖层本地构建镜像、不暴露直连端口可以.env.example面向用户的配置模板版本号在此锁定可以——升级版本时需同步更新.env.testCI 专用配置仅内部使用内部otel-collector-config.yamlOTEL Collector 管道配置可以traefik-local-tls.yml本地 TLS 的 Traefik 动态配置可以project.jsonNX 工程定义test-config/test-run/test-e2e/test/test-full/stopNX 自动管理这里有一条值得牢记的组合性规则每个docker-compose.mode-*.yml覆盖层必须能够只与基础文件组合独立工作禁止把模式相关配置合并进基础 docker-compose.yml。NX 的test-config目标正是通过逐组合执行docker compose config --quiet来机械化验证这一点的见 project.json。三、Traefik 路由规则优先级表与 h2c 统一转发模型这是该部署栈最核心的技术点。Traefik 通过 Docker label 为${ZITADEL_DOMAIN}建立四组路由webHTTP 与websecureHTTPS 两个入口点拥有完全相同的规则集优先级规则目标中间件400Path(/)zitadel-loginreplacepath/ui/v2/login/250PathPrefix(/ui/v2/login)zitadel-login—200PathPrefix(/api)zitadel-apistripprefix/api100其余一切OIDC、SAML、gRPC、gRPC-web、API v2 REST 等zitadel-apih2c后端—对应源码见 docker-compose.ymlAPI 侧 label与 L159-L183Login 侧 label。有三个设计要点需要展开3.1 为什么不需要独立的 gRPC 路由器基础文件中有一条显式注释L96-L97# Note: no dedicated gRPC router needed. All gRPC and Connect-RPC traffic # is handled by the catch-all router below since the backend already uses h2c.关键在于 service 级 labelloadbalancer.server.schemeh2cL91Traefik 的后端连接统一走明文 HTTP/2因此gRPCproto/json over h2c、gRPC-web、Connect-RPC、以及 gRPC-gateway 的 REST/JSON全部由同一条 catch-all 路由透传无需按Content-Type: application/grpc*头区分。/api前缀则通过zitadel-strip-api中间件剥离stripprefix.prefixes/api、forceSlashfalseL93-L94后进入同一条 catch-all 路径。这一设计有测试级证据tests/wiring.spec.ts 头部注释列出了完整的API 协议 × 传输矩阵——V1 的AdminService/Healthz覆盖 REST JSONHTTP/1.1 h2c、gRPC-web proto/jsonHTTP/1.1、gRPC proto/jsonh2c共 6 种组合V2 的SessionService/ListSessions则覆盖 gRPC-gateway REST 映射、Connect unaryapplication/json、application/proto与原生 gRPCapplication/grpcproto/grpcjsonh2c only各 × HTTP/1.1 与 h2c。所有流量都从 Traefik 的 catch-all 路由器进入。3.2/api别名与规范路径并存不变量明确写着/api前缀只是便捷别名规范的路由根路径/.well-known/、/oauth/v2/等必须保留。两者并存的原因在 README.md 中给出/api别名存在是为 DX——工具可以使用https://auth.example.com/api/...这样的统一前缀OIDC/SAML 协议要求/.well-known/openid-configuration、/oauth/v2/...等端点保持在根路径任何只允许/api的重写模型都会破坏协议合规性。因此文档将严格/api-only 重写模型列为被明确否决的替代方案见第六节。冒烟检查命令curl -sS http://localhost:8888/.well-known/openid-configuration来自 AGENTS.md 第 5 节正是直接命中这条根路径规范端点来验证的。3.3 根路径改写与登录 UIPath(/)的 400 优先级路由器把站点根路径经replacepath中间件改写到/ui/v2/login/L159保证用户直接访问域名根时落到新版登录 UI。Login 容器同时设置NEXT_PUBLIC_BASE_PATH: /ui/v2/login与CUSTOM_REQUEST_HEADERS: Host:${ZITADEL_DOMAIN},X-Forwarded-Proto:${ZITADEL_PUBLIC_SCHEME}前者决定 Next.js 的资源基路径后者用于 Login 服务端代理请求 API 时携带正确的 Host 头API 按 Host 做多实例解析见下节。四、External 三件套不变量最常见的部署故障根源AGENTS.md 第 3 节与 README.md 都把同一条不变量标注为单一最常见部署问题ZITADEL_EXTERNALDOMAIN、ZITADEL_EXTERNALPORT、ZITADEL_EXTERNALSECURE必须与实际公网端点一致。不一致会导致 Instance not found 错误。机制可以从基础文件的环境变量推导API 收到请求后按Host头加上端口/协议语义去实例表中查找逻辑实例如果容器内声明的外部 URL 与用户浏览器实际访问的 URL 对不上例如域名写auth.example.com而端口写成8080或ZITADEL_EXTERNALSECURE与 TLS 终结方式不匹配查找必然失败。这三个变量在基础文件中注入docker-compose.ymlZITADEL_EXTERNALDOMAIN: ${ZITADEL_DOMAIN} ZITADEL_EXTERNALPORT: ${ZITADEL_EXTERNALPORT} ZITADEL_EXTERNALSECURE: ${ZITADEL_EXTERNALSECURE}而 Login UI 的基址ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_BASEURI、ZITADEL_OIDC_DEFAULTLOGINURLV2、ZITADEL_OIDC_DEFAULTLOGOUTURLV2、ZITADEL_SAML_DEFAULTLOGINURLV2由ZITADEL_PUBLIC_SCHEME 上述变量拼接而成L52-L55。TLS 覆盖层则会整体覆盖这组 URL 为https://${ZITADEL_DOMAIN}/...并把ZITADEL_EXTERNALPORT硬置为443、ZITADEL_EXTERNALSECURE: true——例如 docker-compose.mode-letsencrypt.yml 中对zitadel-api与zitadel-login的 environment 覆盖。五、四种运行模式详解5.1 本地开发模式基础文件单独使用AGENTS.md 第 5 节给出的启动命令cp .env.example .env docker compose up -d --wait.env.example 文件头部明确标注INSECURE DEFAULTS — for local development only上线前必须更换ZITADEL_MASTERKEY、POSTGRES_ADMIN_PASSWORD等值。几个关键取值ZITADEL_DOMAINlocalhost、PROXY_HTTP_PUBLISHED_PORT8080、ZITADEL_EXTERNALPORT8080、ZITADEL_EXTERNALSECUREfalse——三者一致地描述HTTP、8080 端口、localhost这一公网端点ZITADEL_MASTERKEY必须恰好 32 字符示例值MasterkeyNeedsToHave32Characters即满足ZITADEL_DATABASE_POSTGRES_DSNpostgresql://postgres:postgrespostgres:5432/zitadel?sslmodedisable——注释特别说明配置 DSN 后 ZITADEL 不会创建/切换非特权用户DSN 中的用户将被直接使用生产环境建议配置为仅具备所需权限的非超级用户角色镜像版本在此统一锁定ZITADEL_VERSIONv4.16.0、TRAEFIK_IMAGEtraefik:v3.7.7、POSTGRES_IMAGEpostgres:17.10-alpine、REDIS_IMAGEredis:7.4.9-alpine、OTEL_COLLECTOR_IMAGEotel/opentelemetry-collector-contrib:0.156.0升级流程是改.env版本号 →pull→up -d --wait。基础文件中 API 的启动命令是start-from-init --masterkey ${ZITADEL_MASTERKEY}L35即初始化与启动合并为单容器完成bootstrap 相关环境变量ZITADEL_FIRSTINSTANCE_LOGINCLIENTPATPATH、ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_*、LOGIN_CLIENT_PAT_EXPIRATION会在初始化时创建名为login-client的 IAM 机器用户并把其 PAT 写入共享卷zitadel-bootstrap的/zitadel/bootstrap/login-client.pat供 Login 容器以ZITADEL_SERVICE_USER_TOKEN_FILE消费L128-L131。5.2 Lets Encrypt 模式docker compose --env-file .env -f docker-compose.yml -f docker-compose.mode-letsencrypt.yml up -d --waitdocker-compose.mode-letsencrypt.yml 在基础命令之上追加了 ACME 配置--certificatesresolvers.le.acme.httpchallengetrue使用web入口点完成 HTTP challengeports用 YAML 合并键!override覆盖为80:80与443:443并新增letsencrypt命名卷存放acme.json。LETSENCRYPT_EMAIL在 .env.example 中提供。5.3 External TLS 模式上游 LB 终结# 与 Lets Encrypt 模式同样的 -f 组合方式换成 mode-external-tls 覆盖层docker-compose.mode-external-tls.yml 的要点只发布80:80443 由上游负载均衡器终结通过--entrypoints.web.forwardedHeaders.trustedIPs${TRAEFIK_TRUSTED_IPS}信任来自上游的X-Forwarded-*头TRAEFIK_TRUSTED_IPS在 .env.example 中默认设置为三大私有网段 CIDR10.0.0.0/8,172.16.0.0/12,192.168.0.0/16注释提醒需改成实际的 LB/反向代理网段API 侧同样覆盖为EXTERNALPORT443/EXTERNALSECUREtrue与https://登录 URL。5.4 Local TLS 模式自签证书docker-compose.mode-local-tls.yml 的差异挂载./certs目录只读与 traefik-local-tls.yml 作为 Traefik 动态配置文件动态配置内容极其简洁——一个默认 TLS store 指向/certs/local.crt与/certs/local.keytls: stores: default: defaultCertificate: certFile: /certs/local.crt keyFile: /certs/local.key启用web入口点到websecure的强制 HTTPS 重定向--entrypoints.web.http.redirections.entrypoint.towebsecure80/443 双端口经!override发布。5.5 Production-like 模式init / setup / start 三段拆分docker compose --env-file .env -f docker-compose.yml -f docker-compose.prodlike.yml up -d --waitdocker-compose.prodlike.yml 把一个长驻容器拆成三个短生命周期步骤便于在故障时单独重放某一段zitadel-initcommand: initrestart: no只做数据库初始化zitadel-setupcommand: setup --masterkey ...执行首实例引导创建组织、login-client机器用户与 PAT 等环境变量组与基础文件的zitadel-api相同通过 YAML 锚点zitadel-db-env/*zitadel-db-env共享 DSN依赖zitadel-init以service_completed_successfully完成后才启动zitadel-apicommand从start-from-init覆盖为start --masterkey ...仅承担日常运行依赖 setup 成功完成。这与单容器模式的start-from-init语义等价只是把阶段边界显式化。5.6 可选 profileRedis 缓存与 OTEL 可观测性两者默认关闭启用方式是给docker compose up追加--profilecache.env.example 中ZITADEL_CACHES_CONNECTORS_REDIS_ENABLEDfalse、ZITADEL_CACHES_CONNECTORS_REDIS_URLredis://redis:6379/0以及三个空的*_CONNECTOR变量启用时需打开开关并把 connector 切到 redis。基础文件中的redis服务还显式关闭了持久化--save 、--appendonly no语义是纯缓存。observabilityAPI 默认ZITADEL_INSTRUMENTATION_TRACE_EXPORTER_TYPEnone启用后 collector 在 4317gRPC/4318HTTP接收 trace。otel-collector-config.yaml 的管道是otlp → batch → debugtrace 默认打到 stdout要转发到自有后端Grafana Tempo、Jaeger、OpenObserve 等则取消otlpexporter 的注释并设置OTEL_BACKEND_ENDPOINT同时把exporters改为[debug, otlp]。此外 .env.example 预留了一组 Login 侧 OTEL 变量LOGIN_OTEL_SERVICE_NAME等注释标明当前 login 镜像可能忽略它们属于future-ready placeholders。六、CI 测试体系所有流量必须穿过 TraefikAGENTS.md 第 3 节最后一条不变量规定CI 测试必须走 Traefik测试覆盖层不得暴露容器直连端口所有冒烟流量经代理以端到端验证路由。这一条在 docker-compose.test.yml 中落实得很直接仅把zitadel-api/zitadel-login的镜像换成本地构建的zitadel/zitadel:local、zitadel/zitadel-login:local注释说明由 NX 的zitadel/api:packzitadel/login:pack产出不覆盖任何端口发布——基础文件中proxy唯一发布的是${PROXY_HTTP_PUBLISHED_PORT}:80.env.test 把它设为8888测试流量全部走localhost:8888额外注入ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD等首实例变量播种已知管理员密码与一个zitadel-admin-sa机器用户PAT 写入/zitadel/bootstrap/admin.pat供外部验收测试消费管理 API。NX 目标project.json与职责目标行为需要 Dockertest-config对全部 5 种覆盖层组合执行docker compose config --quiet语法校验否test-run先构建本地镜像依赖zitadel/api:pack、zitadel/login:pack再up --force-recreate --wait启动zitadel-compose-test栈是test-e2ePlaywright 套件wiring.spec.tssmoke.spec.ts打localhost:8888是栈须已运行test轻量版只委托test-config对nx affected安全否test-full全流水线test-config→test-run→ Playwright → 无论成败都执行stop清理是stopdown --volumes拆除测试栈并删除卷是两个 Playwright 测试的定位摘自 tests/smoke.spec.ts 与 tests/wiring.spec.ts 头部注释wiring 测试回答每个服务与协议经代理是否可达——覆盖 Login UI、ConsoleAngular SPA、OIDC discovery/keys、SAML metadata、根路径重定向以及上文 3.1 节完整的 API 协议×传输矩阵smoke 测试回答整条链是否工作——一次成功的用户名/密码登录即证明浏览器 → Traefik(8888) → zitadel-login → zitadel-api → postgres每一环都通。测试凭据读自SMOKE_TEST_ADMIN_USERNAME/SMOKE_TEST_ADMIN_PASSWORD.env.test 中为zitadel-adminzitadel.localhost/Password1!用户名格式为usernameorg-domain.external-domain。七、关键不变量与被否决的替代方案本节是 AGENTS.md 第 3、4 节的完整继承也是后续维护者包括 AI Agent修改该目录时的硬约束。必须保持的不变量四种 TLS 模式保持独立可组合模式配置永不合并进基础文件gRPC 路由不使用/grpc路径前缀源码实现上靠h2c后端方案统一透传见 3.1 节External 三件套ZITADEL_EXTERNALDOMAIN/EXTERNALPORT/EXTERNALSECURE与实际公网端点一致cache/observabilityprofile 为可选不得影响默认栈行为/api别名与规范根路径共存不得移除规范路由镜像版本在.env.example中锁定升级版本必须同步更新该文件CI 测试必须走 Traefik测试覆盖层不暴露直连端口。被考虑过并被明确否决的设计不要重新提议替代方案否决理由单容器合并 API Login不符合 v4 架构——Login 是独立的 Next.js 进程/grpc路径前缀路由gRPC 客户端/工具不使用路径前缀存在兼容性风险严格/api-only 重写模型破坏 OIDC/SAML 规范协议路径Login 使用network_mode: service:脆弱、端口冲突、与 Traefik 路由不兼容合并的 TLS 配置每种模式必须可独立组合且无副作用README.md 还补充了第 6 条被否决项基于HeaderRegexp(Content-Type, ^application/grpc.*)的专用 gRPC 路由器——因为h2c后端方案已原生覆盖 gRPC、gRPC-web 与 Connect-RPC 三种协议专用路由器是冗余的。八、常用命令速查与术语约定来自 AGENTS.md 第 5 节的命令表配合本仓库当前文件结构可直接执行均在deploy/compose/目录下任务命令启动本地开发cp .env.example .env docker compose up -d --wait启动Lets Encryptdocker compose --env-file .env -f docker-compose.yml -f docker-compose.mode-letsencrypt.yml up -d --wait启动生产近似docker compose --env-file .env -f docker-compose.yml -f docker-compose.prodlike.yml up -d --wait校验全部配置对每个覆盖层执行docker compose --env-file .env.example -f docker-compose.yml -f overlay config /dev/null运行 CI 冒烟测试pnpm nx run zitadel/compose:test-full冒烟检查curl -sS http://localhost:8888/.well-known/openid-configuration术语约定遵循根目录 AGENTS.md 术语表Instance ZITADEL 的逻辑租户/分区面向用户文本中绝不使用 exampleSystem 整个 ZITADEL 安装/部署。小结deploy/compose目录的这套部署方案的工程精髓在于**基础栈 正交覆盖层的组合模型**一个必须可独立工作的 docker-compose.yml四个互不依赖的 TLS/prodlike 覆盖层两份职责分明的 env 文件外加一条由test-config静态校验到test-full经 Traefik 的全协议矩阵端到端测试机械守护的组合性契约。对部署者而言最需要内化的是 external 三件套一致性与规范路径不可移动两条规则对维护者而言AGENTS.md 中的不变量清单与被否决替代方案表就是防止架构漂移的第一道防线。【免费下载链接】zitadelZITADEL - Identity infrastructure, simplified for you.项目地址: https://gitcode.com/GitHub_Trending/zi/zitadel创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

TigerBeetle 两阶段转账 Ruby 实战指南:用 Pending/Post 实现可回滚的资金划转 2026/9/14 10:50:32

TigerBeetle 两阶段转账 Ruby 实战指南:用 Pending/Post 实现可回滚的资金划转

TigerBeetle 两阶段转账 Ruby 实战指南:用 Pending/Post 实现可回滚的资金划转 【免费下载链接】tigerbeetle The financial transactions database designed for mission critical safety and performance. 项目地址: https://gitcode.com/GitHub_Trending/ti/ti…

阅读更多 →
Telegraf InfluxDB Input Plugin 详解:从 `/debug/vars` 采集 InfluxDB v1 与兼容端点指标 2026/9/14 10:50:32

Telegraf InfluxDB Input Plugin 详解:从 `/debug/vars` 采集 InfluxDB v1 与兼容端点指标

Telegraf InfluxDB Input Plugin 详解:从 /debug/vars 采集 InfluxDB v1 与兼容端点指标 【免费下载链接】telegraf Agent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data. 项目地址: https://gitcode.com/GitHu…

阅读更多 →
Megatron-LM 与 Megatron Core 全解析:从双组件架构、快速安装到千卡级分布式训练实践 2026/9/14 10:50:32

Megatron-LM 与 Megatron Core 全解析:从双组件架构、快速安装到千卡级分布式训练实践

Megatron-LM 与 Megatron Core 全解析:从双组件架构、快速安装到千卡级分布式训练实践 【免费下载链接】Megatron-LM Ongoing research training transformer models at scale 项目地址: https://gitcode.com/GitHub_Trending/me/Megatron-LM 导读 本文以当…

阅读更多 →
零基础AI绘画上手指南:10分钟画出第一张图,附全套资源清单 2026/9/14 10:50:32

零基础AI绘画上手指南:10分钟画出第一张图,附全套资源清单

零基础AI绘画上手指南:10分钟画出第一张图,附全套资源清单 【免费下载链接】awesome-ai-painting AI绘画资料合集(包含国内外可使用平台、使用教程、参数教程、部署教程、业界新闻等等) Stable diffusion、AnimateDiff、Stable Ca…

阅读更多 →
SpringBoot宿舍管理系统开发实践与架构设计 2026/9/14 10:50:32

SpringBoot宿舍管理系统开发实践与架构设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
SpringBoot校园墙系统设计与实现:从架构到优化 2026/9/14 10:47:32

SpringBoot校园墙系统设计与实现:从架构到优化

1. 项目背景与核心功能 校园墙系统作为高校信息化建设的重要组成部分,已经成为学生日常交流、信息共享的关键平台。这个基于SpringBoot的校园墙系统设计初衷是解决传统校园信息发布存在的三个痛点:信息分散难聚合、互动形式单一、管理效率低下。系统采用…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞