用 Dockerfile 构建镜像时用 build secrets 安全优雅地传递敏感数据
起因是这样的,我有一个 Go 写的 utils
库,但这个仓库目前是 private 的,于是在其他引用了这个库的项目构建时就需要解决鉴权访问的问题。
先来看看不使用私有库的 Go 项目构建的 Dockerfile:
# build api
FROM golang:1.23 AS builder
WORKDIR /src/app
COPY . ./
RUN --mount=type=cache,target=/go/pkg/mod \
make
# build the final image
FROM ubuntu:24.04
COPY --from=builder /src/app/bin/api /app/bin/api
而使用了私有库的话,就需要设置 GOPRIVATE
环境变量和鉴权。
在本地开发的时候我是用的 ssh
来访问 git 仓库的,所以在 ~/.gitconfig
追加如下配置即可:
[url "[email protected]:"]
insteadOf = https://github.com/
但是使用 Docker 构建的时候继续使用 ssh
就会略麻烦(使用 Deploy key)和不安全(使用个人账号 SSH key),那么细粒度的 Access Token 会是更好的选择。
因为 Access Token 是敏感数据,我们是不能直接写在 Dockerfile 里的,所以你可能会想到那就通过构建参数传进去:
+ARG GITHUB_TOKEN
+ENV TOKEN=$GITHUB_TOKEN
WORKDIR /src/app
COPY . ./
+RUN go env -w GOPRIVATE="github.com/YianAndCode/MY_PRIVATE_GO_PKG"
+RUN git config --global url."https://${TOKEN}:[email protected]/".insteadOf "https://github.com/"
RUN --mount=type=cache,target=/go/pkg/mod \
make
然后构建:
export GITHUB_TOKEN=xxx
docker build --build-arg GITHUB_TOKEN=${GITHUB_TOKEN} -t myapp:latest .
这时你会得到一个警告:
WARN: SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data
因为这样做别人在拿到镜像之后是可以看到你构建过程中的参数的,也不安全。其实在 Docker 官方文档有介绍 Build secrets,我们可以利用这个功能来实现更安全优雅地传入敏感数据。
首先来学习一下 build secrets
的基本知识: