1.Buildkit
1.1为什么使用Buildkit
由于containerd无法构建docker镜像,所以需要依赖buildkit来构建镜像
1.2介绍
Buildkit 是一款高效、Docekrfile 无关、更契合 “云原生应用” 的新一代镜像构建工具。
BuildKit 是源自 Docker 的 Moby 项目的第二代镜像构建工具。BuildKit 不限于仅与 Docker 一起使用。这是一种通用的镜像构建工具,可以作为独立的二进制文件(以守护程序或无守护程序模式使用)也可以作为库来使用。实际上,它可以将构建步骤转换成其低级构建器(LLB)表示形式,BuildKit 可用于构建任何制品(artifact)而不仅仅是容器镜像。我们主要在这里关注容器镜像的构建。
1.组成
1.服务端为buildkitd,负责和runc或containerd后端连接干活,目前只支持这两个后端。
2.客户端为buildctl,负责解析镜像构建文件Dockerfile,并向服务端发出构建指令,所以客户端可以和服务端不在一台机器上,也不需要root权限之类。
3.服务端默认使用runc后端,但是建议使用containerd后端,这样构建出的镜像就会存在containerd的buildkit名字空间下。
2.优势
相比于 Docker Daemon build,BuildKit 具有以下优势:
- 更高效:支持并行的多阶段构建、更好的缓存管理;
- 更安全:支持 secret mount,无需 root priviliege;
- 更易于扩展:使用自定义中间语言 LLB,完全兼容 Dockerfile,也可支持第三方语言(目前仅有 Buildpacks),后台目前可支持 runC 和 containerd 两种 worker
3.原理
后台启动一个 buildkitd 守护进程,通过 http 通信的方式执行构建。
- gRPC API: 使用 Google RPC 协议高效通信
- Go client library: 基于 Go 的客户端方便调用
- rootless execution: buildctl 不需要 root 权限就可以执行
- OpenTracing: 支持镜像 layer 的逐层溯源
- multi-worker model:支持多种 worker(runC 和 containerd),可扩展
1.3部署
1.单节点
自从 Containerd 发布 1.5 以后,Kubernetes 的CRI接口使用 Containerd 来替代 dockershim 时, 我们便可以使用 nerdctl 工具(替代 docker cli) 配合 Containerd 的情况下基本已经可以替换掉 Docker 和 Docker Compose 。只有 nerdctl 还不能打包镜像,还需要 BuildKit 服务配置完成打包镜像
版本兼容
buildkit | containerd | docker |
---|---|---|
v0.16.0 | >=v1.7.21 | >= v27.2.1 |
下载
wget https://github.com/moby/buildkit/releases/download/v0.16.0/buildkit-v0.16.0.linux-amd64.tar.gz
wget https://github.com/moby/buildkit/releases/download/v0.16.0/buildkit-v0.16.0.linux-amd64.tar.gz
- 解压
tar xf buildkit-v0.16.0.linux-amd64.tar.gz
#复制文件
cp bin/{buildkitd,buildctl} /usr/local/bin
tar xf buildkit-v0.16.0.linux-amd64.tar.gz
#复制文件
cp bin/{buildkitd,buildctl} /usr/local/bin
创建init文件
- buildkitd
cat <<-EOF | tee /lib/systemd/system/buildkitd.service >> /dev/null
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit
# Requires=buildkit.socket
After=buildkit.socket
[Service]
ExecStart=/usr/local/bin/buildkitd --oci-worker=false --containerd-worker=true
[Install]
WantedBy=multi-user.target
EOF
cat <<-EOF | tee /lib/systemd/system/buildkitd.service >> /dev/null
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit
# Requires=buildkit.socket
After=buildkit.socket
[Service]
ExecStart=/usr/local/bin/buildkitd --oci-worker=false --containerd-worker=true
[Install]
WantedBy=multi-user.target
EOF
- socket
# buildkitd 服务依赖的 socket 文件
cat <<-EOF | tee /lib/systemd/system/buildkit.socket >> /dev/null
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit
[Socket]
ListenStream=%t/buildkit/buildkitd.sock
[Install]
WantedBy=sockets.target
EOF
# buildkitd 服务依赖的 socket 文件
cat <<-EOF | tee /lib/systemd/system/buildkit.socket >> /dev/null
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit
[Socket]
ListenStream=%t/buildkit/buildkitd.sock
[Install]
WantedBy=sockets.target
EOF
- 启动服务
systemctl daemon-reload
systemctl start buildkitd.service
systemctl enable buildkitd.service
systemctl daemon-reload
systemctl start buildkitd.service
systemctl enable buildkitd.service
设置别名
alias docker=nerdctl
alias docker-compose="nerdctl compose"
#持久化请将配置写入 ~/.bashrc 文件中
alias docker=nerdctl
alias docker-compose="nerdctl compose"
#持久化请将配置写入 ~/.bashrc 文件中
验证效果
[root@kube-master-01 Buildkit]# cat Dockerfile
FROM alpine
CMD ["echo", "Hello Docker!!!"]
nerdctl build -t hello:v1 .
[root@kube-master-01 Buildkit]# cat Dockerfile
FROM alpine
CMD ["echo", "Hello Docker!!!"]
nerdctl build -t hello:v1 .
2.docker节点
2018 年 7 月 BuildKit 正式内置于 Docker-ce 18.06.0 的 Docker daemon ,Mac 和 Linux 可以使用环境变量 DOCKER_BUILDKIT=1 开启,同年 10 月发布社区版本。
默认情况下,Buildx 插件以 Docker 驱动程序为目标,该驱动程序使用 Docker 守护程序提供的 BuildKit 库,但存在其固有的局限性。另一个驱动程序是 docker-container,它透明地在容器内启动 BuildKit 来执行构建。它可以提供 BuildKit 全部功能。
启用BUILDKIT
从 Docker 23.0 版本开始,Buildx 是默认的构建工具(Buildx 就是使用 BuildKit 作为构建工具),若使用传统的 docker build
命令,将会出现弃用提示:
DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
Install the buildx component to build images with BuildKit:
https://docs.docker.com/go/buildx/
DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
Install the buildx component to build images with BuildKit:
https://docs.docker.com/go/buildx/
若是 Docker 23.0 版本之前,则还需要通过两种方式启用 Buildkit 功能
export DOCKER_BUILDKIT=1
export DOCKER_BUILDKIT=1
或者
vim /etc/docker/daemon.json
# 配置信息
"features": {"buildkit": true}
vim /etc/docker/daemon.json
# 配置信息
"features": {"buildkit": true}
3.Pod节点
https://github.com/moby/buildkit/tree/master/examples/kubernetes
https://blog.k8s.li/buildkit-on-kubernetes.html
https://blog.frognew.com/2021/06/relearning-container-13.html
2.案例
alpine linux的核心特点是体积小、简单和安全,因此很多人选择alpine镜像作为基础镜像
2.1 alpine
编写一个Dockerfile在docker官方alpine镜像的基础上,安装glibc,同时配置中国时区:
FROM alpine:3.13.5
# Here we install GNU libc (aka glibc) and set C.UTF-8 locale as default.
ENV LANG=C.UTF-8
RUN echo "**** install packages ****" && \
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories &&\
ALPINE_GLIBC_BASE_URL="https://github.com/sgerrand/alpine-pkg-glibc/releases/download" && \
ALPINE_GLIBC_PACKAGE_VERSION="2.33-r0" && \
ALPINE_GLIBC_BASE_PACKAGE_FILENAME="glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
ALPINE_GLIBC_BIN_PACKAGE_FILENAME="glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
ALPINE_GLIBC_I18N_PACKAGE_FILENAME="glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
apk add --no-cache --virtual=.build-dependencies wget ca-certificates && \
echo \
"-----BEGIN PUBLIC KEY-----\
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApZ2u1KJKUu/fW4A25y9m\
y70AGEa/J3Wi5ibNVGNn1gT1r0VfgeWd0pUybS4UmcHdiNzxJPgoWQhV2SSW1JYu\
tOqKZF5QSN6X937PTUpNBjUvLtTQ1ve1fp39uf/lEXPpFpOPL88LKnDBgbh7wkCp\
m2KzLVGChf83MS0ShL6G9EQIAUxLm99VpgRjwqTQ/KfzGtpke1wqws4au0Ab4qPY\
KXvMLSPLUp7cfulWvhmZSegr5AdhNw5KNizPqCJT8ZrGvgHypXyiFvvAH5YRtSsc\
Zvo9GI2e2MaZyo9/lvb+LbLEJZKEQckqRj4P26gmASrZEPStwc+yqy1ShHLA0j6m\
1QIDAQAB\
-----END PUBLIC KEY-----" | sed 's/ */\n/g' > "/etc/apk/keys/sgerrand.rsa.pub" && \
wget \
"$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
apk add --no-cache \
"$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
\
rm "/etc/apk/keys/sgerrand.rsa.pub" && \
/usr/glibc-compat/bin/localedef --force --inputfile POSIX --charmap UTF-8 "$LANG" || true && \
echo "export LANG=$LANG" > /etc/profile.d/locale.sh && \
\
apk del glibc-i18n && \
\
rm "/root/.wget-hsts" && \
apk del .build-dependencies && \
rm \
"$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_I18N_PACKAGE_FILENAME"
RUN apk update --no-cache && apk add ca-certificates --no-cache && \
apk add tzdata --no-cache && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
FROM alpine:3.13.5
# Here we install GNU libc (aka glibc) and set C.UTF-8 locale as default.
ENV LANG=C.UTF-8
RUN echo "**** install packages ****" && \
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories &&\
ALPINE_GLIBC_BASE_URL="https://github.com/sgerrand/alpine-pkg-glibc/releases/download" && \
ALPINE_GLIBC_PACKAGE_VERSION="2.33-r0" && \
ALPINE_GLIBC_BASE_PACKAGE_FILENAME="glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
ALPINE_GLIBC_BIN_PACKAGE_FILENAME="glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
ALPINE_GLIBC_I18N_PACKAGE_FILENAME="glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
apk add --no-cache --virtual=.build-dependencies wget ca-certificates && \
echo \
"-----BEGIN PUBLIC KEY-----\
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApZ2u1KJKUu/fW4A25y9m\
y70AGEa/J3Wi5ibNVGNn1gT1r0VfgeWd0pUybS4UmcHdiNzxJPgoWQhV2SSW1JYu\
tOqKZF5QSN6X937PTUpNBjUvLtTQ1ve1fp39uf/lEXPpFpOPL88LKnDBgbh7wkCp\
m2KzLVGChf83MS0ShL6G9EQIAUxLm99VpgRjwqTQ/KfzGtpke1wqws4au0Ab4qPY\
KXvMLSPLUp7cfulWvhmZSegr5AdhNw5KNizPqCJT8ZrGvgHypXyiFvvAH5YRtSsc\
Zvo9GI2e2MaZyo9/lvb+LbLEJZKEQckqRj4P26gmASrZEPStwc+yqy1ShHLA0j6m\
1QIDAQAB\
-----END PUBLIC KEY-----" | sed 's/ */\n/g' > "/etc/apk/keys/sgerrand.rsa.pub" && \
wget \
"$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
apk add --no-cache \
"$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
\
rm "/etc/apk/keys/sgerrand.rsa.pub" && \
/usr/glibc-compat/bin/localedef --force --inputfile POSIX --charmap UTF-8 "$LANG" || true && \
echo "export LANG=$LANG" > /etc/profile.d/locale.sh && \
\
apk del glibc-i18n && \
\
rm "/root/.wget-hsts" && \
apk del .build-dependencies && \
rm \
"$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
"$ALPINE_GLIBC_I18N_PACKAGE_FILENAME"
RUN apk update --no-cache && apk add ca-certificates --no-cache && \
apk add tzdata --no-cache && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
2.2 busybox
busybox是一个集成了一百多个最常用的Linux命令和工具的软件工具箱
FROM busybox:1.33.1-glibc
COPY zoneinfo /usr/share/zoneinfo/
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
FROM busybox:1.33.1-glibc
COPY zoneinfo /usr/share/zoneinfo/
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
参考: