docker buildx 相关总结
从 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 --verbosemount 支持
RUN --mount=type=... 一共支持 5 种不同的挂载类型。所有的挂载类型都是为了解决传统 Docker 构建中常见的痛点:减少不必要的文件复制(减小镜像体积)、加速缓存(提升构建速度)、以及安全地传递敏感信息(提升安全性)。
RUN --mount=type= 支持类型汇总表
挂载类型 type= |
核心作用与原理解释 | 典型适用场景 | Dockerfile 示例 (可直接在 RUN 中使用) |
|---|---|---|---|
bind(默认类型) |
只读绑定挂载。 将构建上下文(宿主机目录)或其他镜像阶段的文件临时挂载到容器中执行。执行完后不留在镜像层中,省去了 COPY 步骤。 |
1. 挂载源码进行编译(无需COPY源码) 2. 挂载 requirements.txt 或 package.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_hostsRUN --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 |
其中 bind、cache 和 tmpfs 属于容器内部/上下文的处理,不需要在构建时加额外的命令参数。
但是 secret 和 ssh 涉及到读取宿主机外部的敏感环境,因此必须在 docker build 时传入对应参数才能生效。
要使用以上所有高级 --mount 特性,强烈建议在你的 Dockerfile 的第一行加上官方的 Syntax 声明,以确保 Docker 使用最新版本的解析器:
# syntax=docker/dockerfile:1
FROM ubuntu:22.04
# ... 下面开始写你的 RUN --mount ...type=secret 的构建命令
假设你的 Token 写在宿主机的一个文件里(如 my-token.txt):
# Dockerfile 里的 id=my_token 需要和构建命令里的 id 对应
docker build --secret id=my_token,src=./my-token.txt -t my-app .type=ssh 的构建命令
# 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 .