Docker 支持 GitHub Actions OIDC,CI/CD 告别长期密钥

2026 年 7 月 31 日,Docker 官方博客宣布为 GitHub Actions 提供 OIDC(OpenID Connect)连接。这一能力让 CI/CD 流水线可以用"短时、每次运行独立"的令牌完成 Docker Hub 认证,替代过去长期存储在仓库里的个人访问令牌(PAT)或组织访问令牌(OAT)。

对靠 GitHub Actions 自动构建镜像的团队来说,这几乎是零成本的安全升级:不用改构建逻辑,不用新增基础设施,只换一种认证方式,就把"泄露一次密钥等于账号裸奔"的风险大幅压下去。尤其对同时维护十几个仓库、几十条流水线的团队,过去散落在各仓库 Secret 里的 PAT,现在统一收口到组织级的连接配置里,审计和权限回收都省心得多。

长期密钥的痛点

每个需要推送或拉取 Docker 镜像的 GitHub Actions 工作流,过去都要用一个存成 GitHub Secret 的 PAT 或 OAT 来认证。这些凭据长期有效,一旦泄露,攻击者可以拉取私有镜像、甚至推送恶意镜像,而且这种访问会一直持续到被发现并撤销。轮换靠人工,随着流水线变多,要追踪的凭据越来越多,过期令牌也常常成为审计中的常见问题。

OIDC 方案的思路,与 AWS 的 GitHub Actions OIDC、GCP 的 Workload Identity Federation 一脉相承:不再信任"你存了什么",而是信任"你来自哪里"

维度 传统 PAT/OAT Docker OIDC 连接
令牌有效期 数月到数年 单次运行,几分钟过期
存储方式 仓库 Secret 不存储,运行时动态签发
泄露影响 长期可复用 一次泄露即失效
权限范围 组织/账号级 ruleset 限定的资源
轮换成本 人工,易遗漏 无需轮换

工作流程是怎样的

  1. GitHub 签发一个带签名的身份令牌(JWT),内含仓库、分支、环境等本次运行的信息;
  2. 工作流通过 docker/login-action 把令牌提交给 Docker;
  3. Docker 用 GitHub 公钥验证签名,并按管理员在控制台配置的 ruleset 规则比对;
  4. 校验通过后,Docker 返回一个短时有效、且作用域限定在该 ruleset 资源上的访问令牌;
  5. 后续的 docker pulldocker pushdocker build 照常工作。

整个过程中没有任何存储的密钥或 API token,短时令牌几分钟内过期且无法复用。

迁移步骤

  • 创建连接:登录 Docker Home,进入组织的 OIDC 连接页面,创建连接并配置 ruleset(每个连接最多 5 条),用 repo:组织/仓库:ref:refs/heads/main 这类 subject claim 精确锁定仓库与分支。
  • 更新工作流:加上 permissions: id-token: write,并在 docker/login-action 中通过 DOCKERHUB_OIDC_CONNECTIONID 指定连接 ID。
  • 验证并清理:跑一次流水线确认成功,然后从仓库 Secrets 中删除旧的 PAT/OAT。

改造后的工作流大致长这样:

name: build-and-push

on:
  push:
    branches: [main]

permissions:
  contents: read
  id-token: write   # 让工作流能拿到本次运行的 OIDC 令牌

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
          oidc-connection-id: ${{ secrets.DOCKERHUB_OIDC_CONNECTIONID }}
      - run: |
          docker build -t myorg/app:latest .
          docker push myorg/app:latest

oidc-connection-id 指向管理员在控制台创建的连接,GitHub 侧不需要再存任何长期 Docker 凭据——仓库里那个 DOCKERHUB_TOKEN 用完即可删除。对多仓库、多分支的团队,建议按"生产/预发"分别建连接,把 ruleset 的 subject claim 写得更细,避免一个连接覆盖过多资源。

迁移中的几个注意点

  • 规则匹配要留足空间:ruleset 用 subject claim 精确匹配仓库和分支,写太宽会失去"限定范围"的意义,写太死(比如把 ref 锁死在 refs/heads/main)又会让 PR 预览、feature 分支构建失败。常见做法是对发布分支单独建一条严格 ruleset,其他分支用一条宽松些的兜底。
  • 失败排查有迹可循:如果登录步骤报 oidc 相关错误,先去 Docker 控制台的 OIDC 连接页面看最近尝试记录,对照 GitHub 返回的 subject claim 是否落在 ruleset 里,多半是"分支没匹配上"或"连接 ID 填错"。
  • 权限最小化同样适用:OIDC 只解决"认证",不改变"授权"。给连接绑定的组织账号/命名空间权限仍然按最小可用原则配置,别顺手开成全组织可写。
  • 先小后大:挑一个低风险仓库先迁移跑通,确认日志、镜像标签都正常后再铺开到核心流水线,出问题回退也快——毕竟旧 PAT 在清理前一直是可用的。

需要说明的是:现有 PAT/OAT 依然可用,迁移完全按你自己的节奏进行;本地开发和其他 CI 提供方仍使用 PAT/OAT,Docker 会视需求逐步扩展到更多 CI 平台。

16IDC 观察

"密钥上云、身份下沉"正在成为部署自动化的默认姿势。对站点与 SaaS 团队来说,把 CI 凭据从"长期静态"改为"短期动态"是性价比极高的安全改进——它不改变构建方式,却显著缩小了密钥泄露的爆炸半径。想系统搭建流水线,可以先看GitHub Actions CI/CD 指南;容器与编排基础可以参考Docker 部署入门Kubernetes 入门指南。更多环境部署内容请查看环境部署分类。

原文来源:https://www.docker.com/blog/docker-oidc-connections-for-github-actions-available-for-docker-orgs/
参考:https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect(GitHub OIDC 安全加固文档)