構建機密

構建秘密是任何敏感資訊,例如密碼或 API 令牌,作為應用程式構建過程的一部分使用。

構建引數和環境變數不適合用於向構建傳遞秘密,因為它們會保留在最終映象中。相反,您應該使用秘密掛載或 SSH 掛載,它們可以安全地將秘密暴露給您的構建。

構建秘密型別

  • 秘密掛載是用於將秘密傳遞到構建中的通用掛載。秘密掛載從構建客戶端獲取秘密,並在構建指令執行期間,將其暫時提供給構建容器。這在例如您的構建需要與私有工件伺服器或 API 通訊時非常有用。
  • SSH 掛載是特殊用途的掛載,用於在構建中提供 SSH 套接字或金鑰。它們通常用於您需要在構建中獲取私有 Git 倉庫時。
  • 遠端上下文的 Git 身份驗證是一組預定義的秘密,用於您使用遠端 Git 上下文(也是私有倉庫)進行構建時。這些秘密是“預檢”秘密:它們不在您的構建指令中消耗,但它們用於向構建器提供獲取上下文所需的憑據。

使用構建秘密

對於秘密掛載和 SSH 掛載,使用構建秘密是一個兩步過程。首先,您需要將秘密傳遞到 docker build 命令中,然後您需要在 Dockerfile 中使用該秘密。

要將秘密傳遞給構建,請使用 docker build --secret 標誌,或 Bake 的等效選項。

$ docker build --secret id=aws,src=$HOME/.aws/credentials .
variable "HOME" {
  default = null
}

target "default" {
  secret = [
    "id=aws,src=${HOME}/.aws/credentials"
  ]
}

要在構建中消耗秘密並使其可訪問 RUN 指令,請在 Dockerfile 中使用 --mount=type=secret 標誌。

RUN --mount=type=secret,id=aws \
    AWS_SHARED_CREDENTIALS_FILE=/run/secrets/aws \
    aws s3 cp ...

秘密掛載

秘密掛載將秘密作為檔案或環境變數暴露給構建容器。您可以使用秘密掛載將敏感資訊(例如 API 令牌、密碼或 SSH 金鑰)傳遞到您的構建中。

來源

秘密的來源可以是檔案環境變數。當您使用 CLI 或 Bake 時,可以自動檢測型別。您也可以使用 type=filetype=env 明確指定。

以下示例將環境變數 KUBECONFIG 掛載到秘密 ID kube,作為構建容器中 /run/secrets/kube 處的檔案。

$ docker build --secret id=kube,env=KUBECONFIG .

當您使用環境變數中的秘密時,您可以省略 env 引數,以將秘密繫結到與變數同名的檔案。在以下示例中,API_TOKEN 變數的值掛載到構建容器中的 /run/secrets/API_TOKEN

$ docker build --secret id=API_TOKEN .

目標

在 Dockerfile 中使用秘密時,預設情況下秘密會掛載到檔案中。秘密在構建容器內的預設檔案路徑是 /run/secrets/<id>。您可以使用 Dockerfile 中 RUN --mount 標誌的 targetenv 選項來自定義秘密在構建容器中的掛載方式。

以下示例獲取秘密 ID aws 並將其掛載到構建容器中 /run/secrets/aws 處的檔案。

RUN --mount=type=secret,id=aws \
    AWS_SHARED_CREDENTIALS_FILE=/run/secrets/aws \
    aws s3 cp ...

要以不同名稱將秘密掛載為檔案,請在 --mount 標誌中使用 target 選項。

RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
    aws s3 cp ...

要將秘密掛載為環境變數而不是檔案,請在 --mount 標誌中使用 env 選項。

RUN --mount=type=secret,id=aws-key-id,env=AWS_ACCESS_KEY_ID \
    --mount=type=secret,id=aws-secret-key,env=AWS_SECRET_ACCESS_KEY \
    --mount=type=secret,id=aws-session-token,env=AWS_SESSION_TOKEN \
    aws s3 cp ...

可以同時使用 targetenv 選項將秘密同時掛載為檔案和環境變數。

SSH 掛載

如果您想在構建中使用的憑據是 SSH 代理套接字或金鑰,您可以使用 SSH 掛載而不是秘密掛載。克隆私有 Git 倉庫是 SSH 掛載的常見用例。

以下示例使用 Dockerfile SSH 掛載克隆私有 GitHub 倉庫。

# syntax=docker/dockerfile:1
FROM alpine
ADD git@github.com:me/myprivaterepo.git /src/

要將 SSH 套接字傳遞給構建,您可以使用 docker build --ssh 標誌,或 Bake 的等效選項。

$ docker buildx build --ssh default .

遠端上下文的 Git 身份驗證

BuildKit 支援兩個預定義的構建秘密:GIT_AUTH_TOKENGIT_AUTH_HEADER。當您使用遠端私有 Git 倉庫進行構建時,包括以下情況,請使用它們來指定 HTTP 身份驗證引數:

  • 將私有 Git 倉庫作為構建上下文進行構建
  • 使用 ADD 在構建中獲取私有 Git 倉庫

例如,假設您在 https://gitlab.com/example/todo-app.git 上有一個私有 GitLab 專案,並且您想使用該倉庫作為構建上下文執行構建。未經驗證的 docker build 命令會失敗,因為構建器未獲得拉取倉庫的授權。

$ docker build https://gitlab.com/example/todo-app.git
[+] Building 0.4s (1/1) FINISHED
 => ERROR [internal] load git source https://gitlab.com/example/todo-app.git
------
 > [internal] load git source https://gitlab.com/example/todo-app.git:
0.313 fatal: could not read Username for 'https://gitlab.com': terminal prompts disabled
------

要向 Git 伺服器驗證構建器身份,請將 GIT_AUTH_TOKEN 環境變數設定為包含有效的 GitLab 訪問令牌,並將其作為秘密傳遞給構建。

$ GIT_AUTH_TOKEN=$(cat gitlab-token.txt) docker build \
  --secret id=GIT_AUTH_TOKEN \
  https://gitlab.com/example/todo-app.git

GIT_AUTH_TOKEN 也適用於 ADD,可在您的構建中獲取私有 Git 倉庫。

FROM alpine
ADD https://gitlab.com/example/todo-app.git /src

HTTP 身份驗證方案

預設情況下,透過 HTTP 的 Git 身份驗證使用 Bearer 身份驗證方案。

Authorization: Bearer <GIT_AUTH_TOKEN>

如果您需要使用帶有使用者名稱和密碼的基本方案,您可以設定 GIT_AUTH_HEADER 構建秘密。

$ export GIT_AUTH_TOKEN=$(cat gitlab-token.txt)
$ export GIT_AUTH_HEADER=basic
$ docker build \
  --secret id=GIT_AUTH_TOKEN \
  --secret id=GIT_AUTH_HEADER \
  https://gitlab.com/example/todo-app.git

BuildKit 目前只支援 Bearer 和 Basic 方案。

多個主機

您可以按每個主機設定 GIT_AUTH_TOKENGIT_AUTH_HEADER 秘密,這允許您對不同的主機名使用不同的身份驗證引數。要指定主機名,請將主機名作為字尾附加到秘密 ID:

$ export GITLAB_TOKEN=$(cat gitlab-token.txt)
$ export GERRIT_TOKEN=$(cat gerrit-username-password.txt)
$ export GERRIT_SCHEME=basic
$ docker build \
  --secret id=GIT_AUTH_TOKEN.gitlab.com,env=GITLAB_TOKEN \
  --secret id=GIT_AUTH_TOKEN.gerrit.internal.example,env=GERRIT_TOKEN \
  --secret id=GIT_AUTH_HEADER.gerrit.internal.example,env=GERRIT_SCHEME \
  https://gitlab.com/example/todo-app.git