指令解决什么问题
BuildKit 的 RUN --mount=type=ssh 让构建步骤借用宿主 ssh-agent 的转发通道:私钥始终留在宿主内存中,不进构建上下文、不落进镜像层。它主要解决构建期从私有 Git 仓库拉代码的需求。使用前提是构建走 BuildKit(Buildx 或新版 docker build)、Dockerfile 声明 syntax、构建命令带 --ssh 参数,并且宿主的 agent 已加载对应私钥。
基本信息
| 用途 | 构建期通过 SSH 代理访问私有仓库 |
|---|---|
| Dockerfile 写法 | RUN --mount=type=ssh <命令> |
| 构建侧参数 | docker build --ssh default . |
| 前提 | 宿主 ssh-agent 已加载私钥(ssh-add -l 可见) |
| 依赖 | BuildKit,需在 Dockerfile 首行声明 syntax |
典型使用场景
- 构建期 clone 私有 Git 仓库,拉取内部依赖模块
- 执行 git submodule update 获取子模块源码
- 从内部制品服务器拉取构建所需的产物或配置
- 替代把私钥 COPY 进镜像的危险做法,消除镜像内泄露面
- CI 流水线用部署密钥按项目授权,密钥只存在于 runner 的 agent 中
Dockerfile 示例
Dockerfile 示例
# syntax=docker/dockerfile:1.7
FROM alpine:3.20 AS build
RUN apk add --no-cache git openssh-client
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN --mount=type=ssh git clone --depth 1 git@github.com:team/repo.git /src/repo && rm -rf /src/repo/.git
# 说明:--mount=type=ssh 只对这一条 RUN 生效,其他步骤看不到私钥构建侧启用
构建侧启用
eval "$(ssh-agent -s)" # 启动 agent
ssh-add ~/.ssh/id_ed25519 # 加载私钥
ssh-add -l # 确认私钥已加载
docker build --ssh default -t app/api:1.4.2 . # 构建时转发 agent
docker build --ssh key=~/.ssh/deploy_key -t app/api:1.4.2 . # 指定密钥文件要素对照
| 要素 | 位置 | 说明 |
|---|---|---|
| --mount=type=ssh | RUN 行 | 仅该步有效,不会残留到后续层 |
| --ssh default | 构建命令 | 引用 SSH_AUTH_SOCK 指向的 agent |
| --ssh key=路径 | 构建命令 | 直接用指定私钥文件,不依赖 agent |
| known_hosts | Dockerfile 内 | 私有仓库首次连接需要已知主机指纹 |
容器内没有 SSH_AUTH_SOCK 时构建会报错,先在本机确认 ssh-add -l 能列出密钥;CI 环境需要在流水线里显式启动 agent 并加载部署密钥。
构建完成把 .git 目录删掉,避免仓库地址、提交历史和远端配置随镜像分发出去。
使用前的前提检查
- 构建是否走 BuildKit:docker buildx version 能输出,且构建日志出现分步进度
- 宿主 agent 是否真的加载了私钥:ssh-add -l 能列出对应指纹
- 私有仓库指纹是否已写进 known_hosts,避免构建中途等待交互式确认
- CI 环境是否把部署密钥安全注入 runner 的 agent,而不是提交进仓库