BuildKit 使用介绍
Docker 利用 BuildKit 扩展镜像构建功能,如构建多种系统架构的镜像。
介绍
Docker 18.09 引入的 BuildKit,19.03+ 版本开始可以使用 docker buildx build 命令利用 BuildKit 构建镜像。
- 源码:https://github.com/moby/buildkit/
- 镜像:https://hub.docker.com/r/moby/buildkit
- Docker Hub 支持 buildx 实现
启用 BuildKit 特性
- docker v20.10 后默认开启,查看版本是否支持 BuildKit,如下
buildx字样
$ docker buildx version
github.com/docker/buildx v0.8.2-docker 6224def4dd2c3d347eee19db595348c50d7cb491
$ docker info
Client:
Context: default
Debug Mode: false
Plugins:
...
buildx: Docker Buildx (Docker Inc., v0.8.2-docker)
...
Server:
...
Server Version: 20.10.17
...- 若不出现,可以采用如下方式启用该特性
$ cat > ~/.docker/config.json <<EOF
{
"experimental": "enabled"
}
EOF原理
- 本质上
buildx通过调用buildkit的api管理构建任务 - Docker 在 Linux 系统架构下是不支持 arm 架构镜像,通过运行一个新的
buildkit容器让其支持该特性;Docker 桌面版则无需进行此项设置(Mac)- docker 通过在本地运行
buildkit容器,实现支持多架构镜像构建 - buildkit 也可以以服务的方式单独运行,参考
- docker 通过在本地运行
buildkit镜像可参考:https://github.com/docker-practice/buildx- 构建时,通过配置
--platform标志来指定构建输出的目标架构(例如linux/amd64、linux/arm64或darwin/amd64)
安装 buildkit
buildkitd 守护进程需要安装以下组件:
- runc 或 crun
- 容器(如果你想使用容器工作)
启动 buildkitd 守护进程:您需要在主机上以 root 用户身份运行 buildkitd
$ sudo buildkitd- 配置为系统服务,参考
cat <<EOF > /usr/lib/systemd/system/buildkitd.service
[Unit]
Description=buildkitd
After=network.target
[Service]
ExecStart=/usr/local/buildkit/bin/buildkitd
[Install]
WantedBy=multi-user.target
EOF
# 重新加载Unit file
systemctl daemon-reload
# 启动服务
systemctl start buildkitd
# 开机自启动
systemctl enable buildkitdbuildctl 命令使用
- Dockerfile
FROM alpine
RUN echo "built with BuildKit!" > file
CMD ["/bin/sh"]- 构建
buildctl build \
--frontend=dockerfile.v0 \
--local context=. \
--local dockerfile=. \
--output type=docker,name=myimage,dest=out.tar
# 将out.tar导入到containerd中的某个命名空间下
ctr -n test image import out.tar
# 查看镜像
ctr -n test image ls使用
help
新建 builder 实例
- moby/buildkit 默认镜像,镜像说明参考
$ docker buildx create --name builder --driver docker-container- 国内加速镜像
$ docker buildx create --use --name=builder-cn --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master
# 腾讯云优化
$ docker buildx create --use --name=builder-cn --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master-tencent- 查看 builder 实例
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
builder docker-container
builder0 unix:///var/run/docker.sock inactive
default * docker
default default running linux/amd64, linux/386- 使用 builder 实例
$ docker buildx use builder
# * 存在的为当前使用的
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
builder * docker-container
builder0 unix:///var/run/docker.sock inactive
default docker
default default running linux/amd64, linux/386Demo Dockerfile
- Dockerfile
$ mkdir ~/demo
$ cd ~/demo
$ cat > Dockerfile <<EOF
FROM --platform=$TARGETPLATFORM alpine
RUN uname -a > /os.txt
CMD cat /os.txt
EOF说明:
$TARGETPLATFORM是内置变量,由--platform参数来指定- alpine 镜像支持的架构包括:
linux/amd64linux/arm/v6linux/arm/v7linux/arm64/v8linux/386linux/ppc64lelinux/s390x
构建镜像
# 登录docker hub
$ docker login
# 构建并推送
$ docker buildx build --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/386,linux/ppc64le,linux/s390x -t xiexianbin/multi-hello . --push说明:
--push可选,直接推送镜像到 docker hub- 构建过程,默认拉去
pulling image moby/buildkit:buildx-stable-1镜像,本地启动容器creating container buildx_buildkit_builder0即为buildkit的 builder 容器 - 构建日志如下
查看构建的镜像
需要指定 --pull 参数才能查看
$ docker buildx imagetools inspect xiexianbin/multi-hello
Name: docker.io/xiexianbin/multi-hello:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest: sha256:2b15dfe786cdecb59dcc1f710a776a0a3454c1c6923a02a11d0fae495efb7a82
Manifests:
Name: docker.io/xiexianbin/multi-hello:latest@sha256:eeeafa444f5b56d0650b48f0368ebf9034ce1d923d7579c85117367aaf8c8c5d
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/amd64
Name: docker.io/xiexianbin/multi-hello:latest@sha256:a2dd3f3b7778cb1da2e1bc0560300f9dbd7c2dafcfe7186fa6748b6b3c7aa830
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm/v6
Name: docker.io/xiexianbin/multi-hello:latest@sha256:cae98fd2fc1b281dea54b1f353797004907a53b331060661ba8548cec4d1e642
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm/v7
Name: docker.io/xiexianbin/multi-hello:latest@sha256:754f3e4b7cdfb2ec2c36ce911330b5ea8ebc8f9166f96592ea077a4aa8864ca1
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm64
Name: docker.io/xiexianbin/multi-hello:latest@sha256:88671d1de992488e818a2fd224cf2d83a6f72c7b014494a17d75897f2d603ad6
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/386
Name: docker.io/xiexianbin/multi-hello:latest@sha256:6c3d94d4dcb3a61c105581f89ef31689708bf0b1e12eff7b943fa8dfb3baa592
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/ppc64le
Name: docker.io/xiexianbin/multi-hello:latest@sha256:44a705da5e4e212c13b3b03fc651e463a2bcb92f1bc3422eecee3fe6599790c1
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/s390xbuilder 状态
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
builder * docker-container
builder0 unix:///var/run/docker.sock running linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386
default docker
default default running linux/amd64, linux/386Dockerfile
变量
Dockerfile 支持如下架构相关的变量
TARGETPLATFORM构建镜像的目标平台,例如linux/amd64,linux/arm/v7等TARGETOSTARGETPLATFORM的 OS 类型,例如linux,windowsTARGETARCHTARGETPLATFORM的架构类型,例如amd64,armTARGETVARIANTTARGETPLATFORM的变种,该变量可能为空,例如v7
BUILDPLATFORM构建镜像主机平台,例如linux/amd64BUILDOSBUILDPLATFORM的 OS 类型,例如linuxBUILDARCHBUILDPLATFORM的架构类型,例如amd64BUILDVARIANTBUILDPLATFORM的变种,该变量可能为空,例如v7
RUN –mount=type=cache
# syntax = docker/dockerfile:experimental
FROM node:alpine as builder
WORKDIR /app
COPY package.json /app/
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
--mount=type=cache,target=/root/.npm,id=npm_cache \
npm i
COPY src /app/src
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
npm run build
FROM nginx:alpine
RUN --mount=type=cache,target=/root/.npm,from=builder,source=/app/dist \
mkdir -p /app/dist && cp -r /root/.npm/* /app/dist-
--mount=type=cache: 这是 BuildKit 特有的挂载语法。它告诉 Docker 引擎:请给我准备一个持久化的缓存卷。- 这个缓存卷的内容在多次构建(Build)之间是保留的。
- 即使这一层(Layer)的缓存失效了(例如你修改了
package.json),这个挂载卷里的内容依然存在。
-
target=/root/.npm: 这是指定缓存挂载到容器内部的目录路径。- 为什么是
/root/.npm? 因为这是 npm 默认存放下载缓存(Local Cache)的地方(假设你是以 root 用户运行构建)。 - 注意:这里挂载的不是
node_modules,而是 npm 的下载缓存。npm install会先去这个目录找有没有下载过的包,如果有就直接解压,不需要从互联网下载。
- 为什么是
github action
扩展
最近更新
最新评论