在 GitHub Actions 中使用密钥
构建密钥(build secret)是构建过程中使用的一类敏感信息,例如密码或 API 令牌。 Docker Build 支持两种形式的密钥:
本页介绍如何在 GitHub Actions 中使用密钥。 如需了解密钥的整体概念,请参阅 Build secrets。
Secret mounts
下面的示例使用了 GitHub 在工作流中提供的 GITHUB_TOKEN secret
并将其暴露给构建。
首先,创建一个使用该密钥的 Dockerfile:
# syntax=docker/dockerfile:1
FROM alpine
RUN --mount=type=secret,id=github_token,env=GITHUB_TOKEN ...在本例中,密钥名称为 github_token。下面的工作流
通过 secrets 输入将该密钥暴露出来:
name: ci
on:
push:
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build
uses: docker/build-push-action@v7
with:
platforms: linux/amd64,linux/arm64
tags: user/app:latest
secrets: |
"github_token=${{ secrets.GITHUB_TOKEN }}"Note密钥以文件形式挂载到构建容器中。 默认情况下,它们位于
/run/secrets/<id>。 你也可以使用env选项将密钥加载到环境变量中, 或者使用target选项自定义挂载路径。 有关 secret 挂载的详细信息,请参阅 Build secrets。
Secret sources
docker/build-push-action 中用于 secret 挂载的输入项定义了密钥
值的来源。Dockerfile 中的 RUN --mount=type=secret 选项则定义了
构建步骤如何使用该密钥。
| Action 输入 | 来源 | 等效的 Buildx 选项 |
|---|---|---|
secrets: MY_SECRET=value |
工作流中的内联值 | --secret id=MY_SECRET,src=<temp-file> |
secret-envs: MY_SECRET=MY_ENV_VAR |
runner 上的环境变量 | --secret id=MY_SECRET,env=MY_ENV_VAR |
secret-files: MY_SECRET=./secret.txt |
runner 上的文件 | --secret id=MY_SECRET,src=./secret.txt |
例如,RUN --mount=type=secret,id=MY_SECRET 将密钥作为文件
挂载到 /run/secrets/MY_SECRET。若要在 RUN 指令中将同一个密钥
暴露为环境变量,可在 Dockerfile 中使用 env 选项:
RUN --mount=type=secret,id=MY_SECRET,env=MY_SECRET。
Using environment variables as secret sources
secret-envs 输入项会从 GitHub Actions runner 上的环境变量读取密钥。
当某个先前的步骤设置了环境变量,或者你想将 runner 的环境变量
映射为构建中不同的密钥 ID 时,可以使用它。
name: ci
on:
push:
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build
uses: docker/build-push-action@v7
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
with:
context: .
secret-envs: |
sentry_token=SENTRY_AUTH_TOKEN
tags: user/app:latest在 Dockerfile 中,挂载该密钥并将其暴露为需要它的命令所用的环境变量:
# syntax=docker/dockerfile:1
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN --mount=type=secret,id=sentry_token,env=SENTRY_AUTH_TOKEN \
npm run buildUsing secret files
secret-files 输入项让你可以将已有文件作为密钥挂载到构建中。
当你需要使用工作流执行期间生成的凭据文件,
或需要挂载格式已符合要求(如 .npmrc 或 .pypirc)的配置文件时,这会很有用。
secrets、secret-envs 与 secret-files 之间的关键区别:
secrets:从工作流中以字符串形式传入密钥值。secret-envs:从 runner 上的环境变量读取密钥值。secret-files:挂载 runner 文件系统中已有的文件。
Example: Using .npmrc for private npm packages
如果构建需要从私有 npm 注册表安装包,
你可以创建一个 .npmrc 文件并将其作为密钥挂载:
name: ci
on:
push:
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Create .npmrc file
run: |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
- name: Build
uses: docker/build-push-action@v7
with:
context: .
secret-files: |
npmrc=./.npmrc
tags: user/app:latest在 Dockerfile 中,将该密钥文件挂载到预期位置:
# syntax=docker/dockerfile:1
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm ci
COPY . .
RUN npm run build如果 RUN 指令使用非 root 用户,则需要在 secret 挂载上设置 uid、gid 或 mode,
以便该用户能够读取挂载的文件:
RUN --mount=type=secret,id=npmrc,target=/home/node/.npmrc,uid=1000,gid=1000 \
npm ciExample: Using dynamically generated credentials
你可以从多个密钥生成凭据文件并挂载它们:
name: ci
on:
push:
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Create credentials file
run: |
cat <<EOF > aws-credentials
[default]
aws_access_key_id = ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key = ${{ secrets.AWS_SECRET_ACCESS_KEY }}
EOF
- name: Build
uses: docker/build-push-action@v7
with:
context: .
secret-files: |
aws=./aws-credentials
tags: user/app:latest在 Dockerfile 中:
# syntax=docker/dockerfile:1
FROM alpine
RUN apk add --no-cache aws-cli
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
aws s3 cp s3://my-private-bucket/data.tar.gz /tmp/Multi-line secrets
如果你正在使用 GitHub secrets 并且需要处理多行值,则需要将键值对放在引号之间:
secrets: |
"MYSECRET=${{ secrets.GPG_KEY }}"
GIT_AUTH_TOKEN=abcdefghi,jklmno=0123456789
"MYSECRET=aaaaaaaa
bbbbbbb
ccccccccc"
FOO=bar
"EMPTYLINE=aaaa
bbbb
ccc"
"JSON_SECRET={""key1"":""value1"",""key2"":""value2""}"| Key | Value |
|---|---|
MYSECRET |
*********************** |
GIT_AUTH_TOKEN |
abcdefghi,jklmno=0123456789 |
MYSECRET |
aaaaaaaa\nbbbbbbb\nccccccccc |
FOO |
bar |
EMPTYLINE |
aaaa\n\nbbbb\nccc |
JSON_SECRET |
{"key1":"value1","key2":"value2"} |
Note引号需要双重转义。
SSH mounts
SSH 挂载让你可以向 SSH 服务器进行身份验证。
例如执行 git clone,
或从私有仓库获取应用包。
下面的 Dockerfile 示例使用 SSH 挂载 从私有 GitHub 仓库获取 Go 模块。
# syntax=docker/dockerfile:1
ARG GO_VERSION="1.26"
FROM golang:${GO_VERSION}-alpine AS base
ENV CGO_ENABLED=0
ENV GOPRIVATE="github.com/foo/*"
RUN apk add --no-cache file git rsync openssh-client
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
WORKDIR /src
FROM base AS vendor
# this step configure git and checks the ssh key is loaded
RUN --mount=type=ssh <<EOT
set -e
echo "Setting Git SSH protocol"
git config --global url."[email protected]:".insteadOf "https://github.com/"
(
set +e
ssh -T [email protected]
if [ ! "$?" = "1" ]; then
echo "No GitHub SSH key loaded exiting..."
exit 1
fi
)
EOT
# this one download go modules
RUN --mount=type=bind,target=. \
--mount=type=cache,target=/go/pkg/mod \
--mount=type=ssh \
go mod download -x
FROM vendor AS build
RUN --mount=type=bind,target=. \
--mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache \
go build ...要构建这个 Dockerfile,你必须在步骤中指定一个构建器可用于 --mount=type=ssh 的 SSH 挂载。
下面的 GitHub Action 工作流使用了第三方 action MrSquaare/ssh-setup-action
在 GitHub runner 上引导 SSH 配置。该 action 会创建一个由 GitHub Action secret SSH_GITHUB_PPK
定义的私钥,并将其添加到 SSH_AUTH_SOCK 处的 SSH agent 套接字文件。构建步骤中的 SSH 挂载
默认假定 SSH_AUTH_SOCK,因此无需显式指定 SSH agent 套接字的 ID 或路径。
name: ci
on:
push:
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Set up SSH
uses: MrSquaare/ssh-setup-action@2d028b70b5e397cf8314c6eaea229a6c3e34977a # v3.1.0
with:
host: github.com
private-key: ${{ secrets.SSH_GITHUB_PPK }}
private-key-name: github-ppk
- name: Build and push
uses: docker/build-push-action@v7
with:
ssh: default
push: true
tags: user/app:latestname: ci
on:
push:
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Set up SSH
uses: MrSquaare/ssh-setup-action@2d028b70b5e397cf8314c6eaea229a6c3e34977a # v3.1.0
with:
host: github.com
private-key: ${{ secrets.SSH_GITHUB_PPK }}
private-key-name: github-ppk
- name: Build
uses: docker/bake-action@v7
with:
set: |
*.ssh=default