构建期凭据的风险在哪
构建要访问私有包源、私有仓库时需要凭据,把凭据放进 ARG 或 ENV 会留在镜像构建历史与层里,docker history、docker save 都能看到明文。BuildKit 的 --mount=type=secret 只在单条 RUN 期间把文件挂到临时挂载点,用完即撤,不写进镜像层。
基本信息
| 风险点 | 构建历史可见、层内残留、缓存复用把凭据带走 |
|---|---|
| 替代方案 | RUN --mount=type=secret,id=xxx,target=/路径 命令 |
| 提供凭据 | docker build --secret id=xxx,src=./token,也支持从环境变量取值 |
| 前提 | BuildKit 构建器(新版 Docker 默认启用) |
| 默认挂载点 | 不写 target 时挂在 /run/secrets/<id> |
典型使用场景
- 私有 npm 源认证:把 .npmrc 以 secret 形式挂进去跑 npm ci
- 内核制品库或私有 pip 源:临时挂 pip.conf 与凭据文件
- 拉取私有 Git 依赖:构建期临时提供 ssh 私钥或访问 token
- 下载内网构件(带签名校验)时需要凭据的步骤
- 对构建产物做签名(如签名安装包)时临时提供密钥材料
- 多阶段构建中只在需要联网的那一步挂载凭据,其余步骤完全隔离
示例
示例
# 不推荐:token 会留在构建历史与镜像层里
ARG NPM_TOKEN
RUN echo "//registry.example.com/:_authToken=$NPM_TOKEN" > /root/.npmrc
# 推荐:单条 RUN 期间临时挂载,用完即撤
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm ci --omit=dev
# 构建时提供机密内容(读取宿主文件里的内容)
docker build --secret id=npmrc,src=$HOME/.npmrc -t app/web:1.0 .几种凭据传递方式
| 方式 | 是否留在镜像里 | 结论 |
|---|---|---|
| ARG 写文件 | 是,构建历史与层内可见 | 不要用于任何真实凭据 |
| ENV 环境变量 | 是,docker inspect 可见 | 等于把凭据写进镜像配置 |
| --mount=type=secret | 否,只在挂载期间存在 | BuildKit 下的推荐做法 |
| COPY 后删除 | 多数情况仍能在层里找到 | 删除只去掉同一层的可见副本 |
凭据只要进过某一层,导出镜像或查看构建历史就能拿到,事后在 Dockerfile 里删掉补不回来,只能重建镜像并更换凭据。
secret 只解决构建期;应用运行期需要的凭据要用运行环境自己的机制(挂载文件、环境变量注入、密钥管理服务),两者不要混为一谈。
secret 的内容不参与层缓存的键计算,更换凭据后依赖它的步骤可能仍然命中旧缓存,必要时用 --no-cache 或换标签重建。