自动构建镜像时,最常见的做法是在 GitHub Secrets 中存一枚 Docker Hub 访问令牌,工作流启动后取出来登录。这种方式直观,但流水线越多,长期凭据的维护就越容易被忽略:谁在使用、何时过期、撤销后影响哪些任务,都需要额外追踪。
OIDC 把登录方式换成了另一种思路:这次任务先证明自己来自哪个仓库、哪个分支,再由 Docker 决定是否授予短期访问能力。长期令牌不再作为每次任务的固定输入,权限判断则从“拿到了什么密码”转向“这次运行是否符合信任规则”。
一次登录包含两种令牌#
GitHub 的身份令牌和 Docker 的访问令牌不是同一个东西。前者证明工作流身份,后者才用于访问镜像仓库。
GitHub Actions 中的构建任务
→ 向 GitHub 请求本次运行的身份令牌
→ 将身份令牌交给 Docker
→ Docker 检查签名、受众与组织配置的规则
→ 返回受限、短期的访问令牌
→ 使用访问令牌拉取或推送镜像这里有两个独立问题。GitHub 需要确认请求令牌的是一个获准的运行任务;Docker 需要确认这个身份是否符合目标组织的信任规则。仅仅打开 GitHub 侧的开关,并不意味着 Docker 会接受任意仓库发来的请求。
Docker 于 2026 年 7 月推出这项组织连接能力时,列出的适用范围包括 Team、Business、DHI 订阅组织和符合条件的开源组织。接入前要核对自己的账号资格,不能把通用 OIDC 原理理解成所有个人账户都能直接使用同一项产品功能。
信任规则要回答谁、从哪里、能做什么#
假设只有 main 分支允许更新正式镜像,其他分支只负责测试。信任规则至少需要明确仓库、分支或部署环境,以及能够访问的镜像资源和操作范围。
| 要素 | 需要回答的问题 | 容易出现的误区 |
|---|---|---|
| 仓库身份 | 是否来自指定代码仓库 | 只限制组织,不限制仓库 |
| 运行上下文 | 分支、标签或部署环境是否符合要求 | 认为所有运行的身份声明都长得一样 |
| 目标资源 | 可以操作哪些镜像仓库 | 一个连接覆盖所有镜像 |
| 操作范围 | 只读还是允许推送 | 构建验证也使用正式推送权限 |
身份声明应以当前工作流实际产生的值为准。仓库标识格式可能受到平台规则、仓库创建时间和自定义声明的影响。排查匹配失败时,应查看实际声明和连接侧的拒绝记录,不能为了让流水线变绿就把规则改成整个组织通配。
id-token: write 到底允许了什么#
GitHub Actions 中,下面这段权限配置允许任务申请 OIDC 身份令牌:
permissions:
contents: read
id-token: write它没有直接给任务授予 Docker 管理员权限,也没有自动允许修改代码。Docker 侧能做什么,仍由连接和资源规则决定。完整工作流还需要组织连接标识、兼容的登录 Action 和具体构建步骤。
申请身份令牌的权限最好放在真正需要镜像登录的 job 上。单元测试、静态检查和文档预览通常没有必要同时获得镜像推送能力。任务边界越清楚,后续排查“为什么这次运行能够发布”就越容易。
登录 Action 本身也属于执行代码。生产流水线应按项目规则固定其版本或提交,升级时核对变更,而不是把凭据换短期之后就忽略工作流依赖。
短期凭据解决不了全部问题#
令牌有效期缩短,可以减少凭据失窃后的持续影响,但有效期内的权限仍然真实存在。如果一个获准推送的任务执行了未经审查的脚本,它仍可能利用这次访问能力推送不应发布的镜像。
因此,不能把“没有保存长期令牌”理解成“所有代码都可以拿到临时推送权限”。外部分支、拉取请求和受信任的发布任务,应当沿着不同的权限路径运行。保护分支、限制发布环境和审查工作流变更,仍然是交付流程的一部分。
同样,登录成功只证明认证环节完成。Dockerfile 是否正确、镜像标签是否符合约定、产物是否通过检查,都还需要独立验证。镜像上传成功之后,生产部署也可能尚未开始。
迁移时先验证,再撤销旧凭据#
可以先选一条影响范围较小的工作流接入,验证三类情况:指定分支成功、非指定分支被拒绝、目标之外的镜像资源无法访问。只测成功路径,会遗漏最重要的权限边界。
迁移期间还要确认实际使用的是哪条登录路径。如果工作流中同时保留旧令牌和 OIDC 配置,即使构建成功,也可能仍然是旧令牌在起作用。验证应结合任务日志和连接侧记录,避免以一次绿色状态代替认证方式核对。
确认新路径有效后,再停用旧 Secrets,并撤销不再需要的 PAT 或组织令牌。删除仓库变量和撤销服务端凭据是两个动作,不能只做其中一个就认为迁移已经结束。
如果其他 CI 平台、本地脚本或外部发布程序仍在使用那枚旧令牌,需要先盘点调用方,再决定撤销时间,避免一次认证改造连带中断其他交付流程。
失败时按环节定位#
身份令牌申请失败,先查 GitHub 任务权限和触发条件;Docker 拒绝兑换,查身份声明、受众和信任规则;登录成功但推送失败,查镜像仓库范围、读写权限和目标名称。
这三个阶段的错误含义不同。把所有失败都处理成“令牌不对,重试一下”,只会让配置问题拖得更久。一次记录清楚失败阶段、工作流运行标识与目标资源,比把完整令牌打印出来更有价值。
对于已有 Docker 镜像发布流程,OIDC 最值得借鉴的是按任务发放权限的方式。先明确什么身份可以发布什么产物,再用短期凭据实现这份约定,认证方式的变化才能真正落到交付边界上。
参考资料#
- Greg Mondello、Dan Stelzer:Docker OIDC connections for GitHub Actions available for Docker Orgs,2026-07-31。
- Docker:OIDC connections。
- GitHub:OpenID Connect。
