一、背景

参考:nerdctl + buildkitd 构建容器镜像_莫测之境的技术博客_51CTO博客 在 k8s 1.24,Dockershim 组件正式从 kubelet 中移除,默认将无法直接使用 Docker Engine 作为容器运行时,而直接使用 containerd 作为容器运行时。

虽然 containerd 自带的 crictl 和 ctr 命令能够进行一些简单的管理,但是并不好用,比如说不支持build镜像。因此使用nerdctl + buildkitd  来管理。

Nerdclt 兼容原来 docker 的大部分命令,还实现了很多 docker 不具备的功能,例如延迟拉取镜像(lazy-pulling),镜像加密(imgcrypt)等。

BuildKit 是由 Docker 公司开发的 下一代 docker build 工具,具有更高效、更安全、易于扩展等特点。BuildKit 是由 buildkitd 守护程序和 buildctl 客户端组成。buildkitd 作为服务端,连接容器运行时,目前支持 runc(or crun)和 containerd 作为镜像构建环境,默认是 runc。
buildctl 作为客户端,负责解析Dockerfile文件,并向buildkitd发出构建请求。由于命令较为复杂,使用 nerdclt 替代。
二、安装
2.1 安装 buildkitd

# 下载二进制文件
wget https://github.com/moby/buildkit/releases/download/v0.11.3/buildkit-v0.11.3.linux-amd64.tar.gz

# 解压
tar xf buildkit-v0.11.3.linux-amd64.tar.gz

# 复制 buildkitd 和 buildctl 到 /usr/local/bin/
cp bin/buildkitd bin/buildctl /usr/local/bin/
# 编写 buildkit 套接字文件

 

cat >> /lib/systemd/system/buildkitd.socket << EOF
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit

[Socket]
ListenStream=%t/buildkit/buildkitd.sock

[Install]
WantedBy=sockets.target

EOF

# 编写 buildkit 服务文件,指定使用 containerd

cat >> /lib/systemd/system/buildkitd.service << EOF
[Unit]
Description=BuildKit
Requires=buildkitd.socket
After=buildkit.socketDocumentation=https://github.com/moby/buildkit
 
[Service]
ExecStart=/usr/local/bin/buildkitd --oci-worker=false --containerd-worker=true
 
[Install]
WantedBy=multi-user.target

EOF
# 启动 buildkitd 守护进程
systemctl daemon-reload
systemctl enable --now buildkitd
systemctl status buildkitd

2.2 安装 nerdclt
# 下载二进制文件

wget https://github.com/containerd/nerdctl/releases/download/v1.2.0/nerdctl-1.2.0-linux-amd64.tar.gz

# 解压
tar xf nerdctl-1.2.0-linux-amd64.tar.gz
mv nerdctl /usr/local/bin/

三、构建镜像
# 测试镜像的 Dockerfile
 

cat >> Dockerfile << EOF
FROM nginx:1.22.1-alpine
RUN apk add --no-cache tzdata ca-certificates \
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
EOF

# 拉取 dockerhub 上的镜像
nerdctl pull  nginx:1.22.1-alpine

# 构建镜像
nerdctl build -t harbor.belkuy.top/base/nginx:1.22.1-alpine .

# 登陆镜像仓库,并推送镜像
nerdctl login harbor.belkuy.top
nerdctl push harbor.belkuy.top/base/nginx:1.22.1-alpine
# 可能遇到报错,加上sudo 和--no-cache 

sudo nerdctl -n k8s.io  build --no-cache -t nginx:custom .

nerdctl 命令


使用镜像

Rancher Desktop 通过 NERDCTL 项目和 Docker CLI 来提供构建,推送和拉取镜像的功能。

请注意,nerdctl 和 docker 都会自动放入路径中。在 Windows 上,这发生在安装程序期间,而在 macOS 和 Linux 上,这发生在首次运行的时候。

常规用法

使用任何一种工具都需要 Rancher Desktop 与适当的容器运行时一起运行。对于 nerdctl,使用 containerd 运行时。对于 docker,使用 Moby 运行时。

要了解所有命令选项并显示帮助文档,运行:

  • nerdctl
  • docker
nerdctl -h

与 Docker 不同,containerd 具有自己的命名空间。默认情况下,nerdctl 镜像存储在 default 命名空间中。如果你希望你的镜像可供 Kubernetes 使用,请使用 --namespace k8s.io 或 -n k8s.io CLI 参数。你还可以使用 --namespace <NAMESPACE_NAME> 选项来切换到 default 或其他命名空间。请注意,nerdctl 命名空间独立于 Kubernetes 和 kubectl 命名空间。

列出镜像

要查看当前可用的镜像,请运行以下命令:

  • nerdctl
  • docker
nerdctl images

构建镜像

  • nerdctl
  • docker

构建镜像与现有工具的操作相似。你可以在具有 DockerfileDockerfile 使用了一个 scratch 镜像)的路径上运行 nerdctl

nerdctl build .
[+] Building 0.1s (4/4) FINISHED
 => [internal] load build definition from Dockerfile
 => => transferring dockerfile: 31B
 => [internal] load .dockerignore
 => => transferring context: 2B
 => [internal] load build context
 => => transferring context: 33B
 => CACHED [1/1] ADD anvil-app /

nerdctl 具有在构建时进行标记的选项以及一些其他选项:

nerdctl build -t TAG .

要构建用于 Kubernetes 的镜像,请指定 k8s.io 命名空间,如下所示:

nerdctl build -n k8s.io .

构建本地镜像

为了演示构建本地镜像和运行应用程序的步骤,Rancher Desktop 的 docs 仓库提供了一个示例 nodejs 应用程序。首先,克隆仓库并 cd 到终端中的 assets/express-sample 中。

运行以下命令来使用 Dockerfile 构建镜像:

  • nerdctl
  • docker
nerdctl --namespace k8s.io build -t expressapp:v1.0 .

运行以下命令来运行容器:

kubectl run --image expressapp:v1.0 expressapp
kubectl port-forward pods/expressapp 3000:3000

注意:添加 latest 标签时,请务必同时指定以下内容:

imagePullPolicy: Never

标记镜像

如果要标记已构建的现有镜像,你可以运行以下命令:

  • nerdctl
  • docker
nerdctl tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

删除镜像

要删除镜像,请运行以下命令:

  • nerdctl
  • docker
nerdctl rmi IMAGE