docker buildx 相关总结

发布时间: 更新时间: 总字数:1128 阅读时间:3m 作者:IP:上海 网址

从 Docker 23.0 (发布于 2023 年 2 月)版本开始,BuildKit 正式成为了 Docker 默认的构建引擎。

Registry 缓存

docker buildx build \
  --cache-to=type=registry,ref=my-registry.com/my-app:cache,mode=max \
  --cache-from=type=registry,ref=my-registry.com/my-app:cache \
  -t my-app:latest .

https://docs.docker.com/build/cache/backends/registry/

# 查看所有的 Cache Mount 及其大小
docker buildx du --filter type=exec.cachemount

# 查看具体每个 Cache 是属于哪个挂载的
docker buildx du --filter type=exec.cachemount --verbose

# 指定 builder
docker buildx du --builder <你的builder名字> --filter type=exec.cachemount --verbose

mount 支持

RUN --mount=type=... 一共支持 5 种不同的挂载类型。所有的挂载类型都是为了解决传统 Docker 构建中常见的痛点:减少不必要的文件复制(减小镜像体积)、加速缓存(提升构建速度)、以及安全地传递敏感信息(提升安全性)

RUN --mount=type= 支持类型汇总表

挂载类型 type= 核心作用与原理解释 典型适用场景 Dockerfile 示例 (可直接在 RUN 中使用)
bind
(默认类型)
只读绑定挂载
将构建上下文(宿主机目录)或其他镜像阶段的文件临时挂载到容器中执行。执行完后不留在镜像层中,省去了 COPY 步骤。
1. 挂载源码进行编译(无需COPY源码)
2. 挂载 requirements.txtpackage.json 安装依赖
RUN --mount=type=bind,source=package.json,target=package.json \
npm install
cache 缓存挂载
为编译器或包管理器(如 pip, npm, apt, go build)提供持久化缓存目录。即使重新构建或更改了源码,只要缓存还在,就能极大提升下载或编译速度。
1. 缓存 pip/npm 下载的依赖包
2. 缓存 apt/apk 软件包
3. 缓存 Go/Java 编译中间产物
# 缓存 Python pip 包
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
secret 机密信息挂载
安全地将宿主机的机密文件(如 Token、云厂商凭证、密码)挂载到容器内。挂载是在内存中进行的,不会写入镜像历史层。
1. 访问需要 Token 的私有 NPM/PyPI 源
2. 使用 AWS/阿里云凭证拉取 S3 文件
# 挂载 AWS 凭证使用 s3 命令
RUN --mount=type=secret,id=aws_creds,target=/root/.aws/credentials \
aws s3 cp s3://my-bucket/data .
ssh SSH 代理挂载
将宿主机的 SSH Agent Socket 转发到容器内,允许容器在构建时使用宿主机的 SSH 密钥进行鉴权(不暴露私钥文件)。
1. 通过 SSH 协议 git clone 私有代码库
2. 下载内部私有 Go Modules
# 利用 SSH 拉取私有仓库代码
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN --mount=type=ssh \
git clone git@github.com:user/repo.git
tmpfs 内存文件系统挂载
将一个基于内存的临时文件系统挂载到容器中。写入这里面的文件速度极快,且构建步骤结束后自动销毁。
1. 执行会产生大量无用临时文件的编译脚本
2. 需要极高 IO 读写速度的临时处理步骤
# 挂载 tmpfs 以加速中间文件生成
RUN --mount=type=tmpfs,target=/temp_build_dir \
./compile_script.sh --out=/app/final.bin

其中 bindcachetmpfs 属于容器内部/上下文的处理,不需要在构建时加额外的命令参数。 但是 secretssh 涉及到读取宿主机外部的敏感环境,因此必须在 docker build 时传入对应参数才能生效。

要使用以上所有高级 --mount 特性,强烈建议在你的 Dockerfile第一行加上官方的 Syntax 声明,以确保 Docker 使用最新版本的解析器:

dockerfile
# syntax=docker/dockerfile:1
FROM ubuntu:22.04
# ... 下面开始写你的 RUN --mount ...

type=secret 的构建命令

假设你的 Token 写在宿主机的一个文件里(如 my-token.txt):

bash
# Dockerfile 里的 id=my_token 需要和构建命令里的 id 对应
docker build --secret id=my_token,src=./my-token.txt -t my-app .

type=ssh 的构建命令

bash
# 1. 启动 ssh-agent(如果没启动的话)
eval $(ssh-agent)

# 2. 将你的私钥添加到 ssh-agent 中(假设你的私钥是 ~/.ssh/id_rsa)
ssh-add ~/.ssh/id_rsa

# 系统会提示你输入私钥密码(如果有的话),并显示 Identity added

# 传入 default 将使用当前宿主机的默认 ssh-agent
docker build --ssh default -t my-app .