Containerd 命令行工具 nerdctl 前面我们介绍了可以使用 ctr 操作管理 containerd 镜像容器,但是大家都习惯了使用 docker cli,ctr 使用起来可能还是不太顺手,为了能够让大家更好的转到 containerd 上面来,社区提供了一个新的命令行工具:nerdctl 。nerdctl 是一个与 docker cli 风格兼容的 containerd 客户端工具,而且直接兼容 docker compose 的语法的,这就大大提高了直接将 containerd 作为本地开发、测试或者单机容器部署使用的效率。
安装 安装nerdctl 同样直接在 GitHub Release 页面下载对应的压缩包解压到 PATH 路径下即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 cd /server/tools # 如果没有安装 containerd,则可以下载 nerdctl-full-<VERSION>-linux-amd64.tar.gz 包进行安装 wget https://github.com/containerd/nerdctl/releases/download/v1.5.0/nerdctl-1.5.0-linux-amd64.tar.gz tar xf nerdctl-1.5.0-linux-amd64.tar.gz mv nerdctl /bin/ # 检查结果 $ nerdctl version WARN[0000] unable to determine buildctl version: exec: "buildctl": executable file not found in $PATH Client: Version: v1.5.0 OS/Arch: linux/amd64 Git commit: b33a58f288bc42351404a016e694190b897cd252 buildctl: Version: Server: containerd: Version: v1.7.3 GitCommit: 7880925980b188f4c97b462f709d0db8e8962aff runc: Version: 1.1.8 GitCommit: v1.1.8-0-g82f18fe0
安装buildkit 在镜像构建时需要我们安装 buildctl 并运行 buildkitd,这是因为 nerdctl build 需要依赖 buildkit 工具。
buildkit 项目也是 Docker 公司开源的一个构建工具包,支持 OCI 标准的镜像构建。它主要包含以下部分:
服务端 buildkitd:当前支持 runc 和 containerd 作为 worker,默认是 runc,我们这里使用 containerd 客户端 buildctl:负责解析 Dockerfile,并向服务端 buildkitd 发出构建请求 buildkit 是典型的 C/S 架构,客户端和服务端是可以不在一台服务器上,而 nerdctl 在构建镜像的时候也作为 buildkitd 的客户端,所以需要我们安装并运行 buildkitd。
所以接下来我们先来安装 buildkit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 # 下载地址 wget https://github.com/moby/buildkit/releases/download/v0.12.1/buildkit-v0.12.1.linux-amd64.tar.gz # 解压文件 cd /server/tools mkdir /opt/buildkit && tar -zxvf buildkit-v0.12.1.linux-amd64.tar.gz -C /opt/buildkit/ ln -s /opt/buildkit/bin/buildctl /usr/local/bin/ ln -s /opt/buildkit/bin/buildkitd /usr/local/bin/ # 使用Systemd来管理buildkitd,创建如下所示的systemd unit文件 cat >> /etc/systemd/system/buildkit.service <<EOF [Unit] Description=BuildKit Documentation=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 buildkit --now systemctl status buildkit # 验证 nerdctl与buildctl $ nerdctl version Client: Version: v1.5.0 OS/Arch: linux/amd64 Git commit: b33a58f288bc42351404a016e694190b897cd252 buildctl: Version: v0.12.1 GitCommit: bb857a0d49f45aa0ce9cd554b78d4075553e20f9 Server: containerd: Version: v1.7.3 GitCommit: 7880925980b188f4c97b462f709d0db8e8962aff runc: Version: 1.1.8 GitCommit: v1.1.8-0-g82f18fe0
常用nerdctl命令 k8s 默认使用k8s.io,而 nerdctl 默认使用 default namspace。如果需要查看 k8s 相关镜像需要加上”--namespace=k8s.io“来指定。
1 2 nerdctl images --namespace=k8s.io nerdctl -n=k8s.io images
或者在 nerdctl 配置文件中指定 nerdctl 默认使用 k8s.io namespace
1 2 3 4 mkdir /etc/nerdctl/ cat >> /etc/nerdctl/nerdctl.toml << EOF namespace = "k8s.io" EOF
Run&Exec nerdctl run 和 docker run 类似可以使用 nerdctl run 命令运行容器,例如:
1 2 $ nerdctl run -d -p 80:80 --name=nginx --restart=always nginx:alpine 883a46df6f5875a6afae26414b498f396ea5e8ca1c24f91f97a2695c7b187ec0
可选的参数使用和 docker run 基本一直,比如 -i、-t、--cpus、--memory 等选项,可以使用 nerdctl run --help 获取可使用的命令选项。
nerdctl exec
同样也可以使用 exec 命令执行容器相关命令,例如:
1 2 3 4 $ nerdctl exec -it nginx /bin/sh / # date Wed Aug 9 08:12:10 UTC 2023 / # ls
容器管理 nerdctl ps :列出容器
使用 nerdctl ps 命令可以列出所有容器。
1 2 3 $ nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 883a46df6f58 docker.io/library/nginx:alpine "/docker-entrypoint.…" 5 minutes ago Up 0.0.0.0:80->80/tcp nginx
同样可选的参数使用和 docker ps 基本一直,比如 -q、-n 等选项,可以使用 nerdctl ps --help 获取可使用的命令选项。
nerdctl inspect :获取容器的详细信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 $ nerdctl inspect nginx [ { "Id": "883a46df6f5875a6afae26414b498f396ea5e8ca1c24f91f97a2695c7b187ec0", "Created": "2023-08-09T08:09:23.347598372Z", "Path": "/docker-entrypoint.sh", "Args": [ "nginx", "-g", "daemon off;" ], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": true, "Pid": 2814, "ExitCode": 0, "Error": "", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "docker.io/library/nginx:alpine", "ResolvConfPath": "/var/lib/nerdctl/1935db59/containers/default/883a46df6f5875a6afae26414b498f396ea5e8ca1c24f91f97a2695c7b187ec0/resolv.conf", "HostnamePath": "/var/lib/nerdctl/1935db59/containers/default/883a46df6f5875a6afae26414b498f396ea5e8ca1c24f91f97a2695c7b187ec0/hostname", "LogPath": "/var/lib/nerdctl/1935db59/containers/default/883a46df6f5875a6afae26414b498f396ea5e8ca1c24f91f97a2695c7b187ec0/883a46df6f5875a6afae26414b498f396ea5e8ca1c24f91f97a2695c7b187ec0-json.log", "Name": "nginx", "RestartCount": 0, "Driver": "overlayfs", "Platform": "linux", "AppArmorProfile": "", "nerdctl/ports": "[{\"HostPort\":80,\"ContainerPort\":80,\"Protocol\":\"tcp\",\"HostIP\":\"0.0.0.0\"}]", "nerdctl/state-dir": "/var/lib/nerdctl/1935db59/containers/default/883a46df6f5875a6afae26414b498f396ea5e8ca1c24f91f97a2695c7b187ec0" } }, "NetworkSettings": { "Ports": { "80/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "80" } ] }, "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "10.4.0.2", "IPPrefixLen": 24, "MacAddress": "4a:5b:f3:cf:cf:eb", "Networks": { "unknown-eth0": { "IPAddress": "10.4.0.2", "IPPrefixLen": 24, "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "4a:5b:f3:cf:cf:eb" } } } } ]
可以看到显示结果和 docker inspect 也基本一致的。
nerdctl logs :获取容器日志
查看容器日志是我们平时经常会使用到的一个功能,同样我们可以使用 nerdctl logs 来获取日志数据:
1 2 $ nerdctl logs -f nginx 10.4.0.1 - - [09/Aug/2023:08:09:46 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.29.0" "-"
同样支持 -f、-t、-n、--since、--until 这些选项。
nerdctl stop :停止容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # stop属于重启重启 $ nerdctl stop nginx nginx $ nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES $ nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 883a46df6f58 docker.io/library/nginx:alpine "/docker-entrypoint.…" 15 minutes ago Up 0.0.0.0:80->80/tcp nginx # kill 属于停止容器 容器状态属于为创建$ nerdctl kill nginx 883a46df6f5875a6afae26414b498f396ea5e8ca1c24f91f97a2695c7b187ec0 $ nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES $ nerdctl ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 883a46df6f58 docker.io/library/nginx:alpine "/docker-entrypoint.…" 17 minutes ago Created 0.0.0.0:80->80/tcp nginx
nerdctl rm :删除容器
1 2 3 $ nerdctl rm nginx container 883a46df6f5875a6afae26414b498f396ea5e8ca1c24f91f97a2695c7b187ec0 is in running status. unpause/stop container first or force $ nerdctl rm -f nginx
如果要强制删除同样可以使用 -f 或 --force 选项来操作。
镜像管理 erdctl images :镜像列表
1 2 3 4 $ nerdctl images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE nginx alpine 1713c88213a0 25 hours ago linux/amd64 43.0 MiB 16.2 MiB $ nerdctl -n=k8s.io images
nerdctl tag :镜像标签
使用 tag 命令可以为一个镜像创建一个别名镜像:
1 2 3 4 5 6 7 8 $ nerdctl images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE nginx alpine 1713c88213a0 25 hours ago linux/amd64 43.0 MiB 16.2 MiB $ nerdctl tag nginx:alpine harbor.boysec.cn/course/nginx:alpine $ nerdctl images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE nginx alpine 1713c88213a0 25 hours ago linux/amd64 43.0 MiB 16.2 MiB harbor.boysec.cn/course/nginx alpine 1713c88213a0 6 seconds ago linux/amd64 43.0 MiB 16.2 MiB
nerdctl pull :拉取镜像
1 $ nerdctl pull docker.io/library/busybox:latest
nerdctl push :推送镜像
当然在推送镜像之前也可以使用 nerdctl login 命令登录到镜像仓库,然后再执行 push 操作。
可以使用 nerdctl login --username xxx --password xxx 进行登录,使用 nerdctl logout 可以注销退出登录。
nerdctl save :导出镜像
使用 save 命令可以导出镜像为一个 tar 压缩包。
1 2 3 $ nerdctl save -o busybox.tar.gz busybox:latest $ ls -lh busybox.tar.gz-rw-r--r-- 1 root root 2.2M Aug 9 16:40 busybox.tar.gz
nerdctl rmi :删除镜像
1 2 3 $ nerdctl rmi busybox Untagged: docker.io/library/busybox:latest@sha256:3fbc632167424a6d997e74f52b878d7cc478225cffac6bc977eedfe51c7f4e79 Deleted: sha256:3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f
nerdctl load :导入镜像
使用 load 命令可以将上面导出的镜像再次导入:
1 2 3 4 $ nerdctl load -i busybox.tar.gz $ nerdctl images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE busybox latest 3fbc63216742 7 seconds ago linux/amd64 4.1 MiB 2.1 MiB
使用 -i 或 --input 选项指定需要导入的压缩包。
镜像构建 镜像构建是平时我们非常重要的一个需求,我们知道 ctr 并没有构建镜像的命令,而现在我们又不使用 Docker 了,那么如何进行镜像构建了,幸运的是 nerdctl 就提供了 nerdctl build 这样的镜像构建命令。
🐳nerdctl build :从 Dockerfile 构建镜像
比如现在我们定制一个 nginx 镜像,新建一个如下所示的 Dockerfile 文件:
1 2 3 4 cat > Dockerfile <<EOF FROM nginx:alpineRUN echo -e "#version wangxiansen\nHello Nerdctl From Containerd" > /usr/share/nginx/html/index.html EOF
然后在文件所在目录执行镜像构建命令:
1 $ nerdctl build -t nginx:nerdctl -f Dockerfile .
构建完成后查看镜像是否构建成功:
1 2 3 4 5 6 $ nerdctl images REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE busybox latest 3fbc63216742 8 minutes ago linux/amd64 4.1 MiB 2.1 MiB nginx alpine 1713c88213a0 25 hours ago linux/amd64 43.0 MiB 16.2 MiB nginx nerdctl a0fd917f4722 47 seconds ago linux/amd64 43.1 MiB 16.2 MiB harbor.boysec.cn/course/nginx alpine 1713c88213a0 12 minutes ago linux/amd64 43.0 MiB 16.2 MiB
我们可以看到已经有我们构建的 nginx:nerdctl 镜像了。接下来使用上面我们构建的镜像来启动一个容器进行测试:
1 2 3 4 5 6 7 8 $ nerdctl run -d -p 80:80 --name=nginx --restart=always nginx:nerdctl 4af4648264330c1ca46ae97299fb03ff7f3c98e9f627618e679eccf6b9df131d $ nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4af464826433 docker.io/library/nginx:nerdctl "/docker-entrypoint.…" 18 seconds ago Up 0.0.0.0:80->80/tcp nginx $ curl localhost # version wangxiansen Hello Nerdctl From Containerd
这样我们就使用 nerdctl + buildkitd 轻松完成了容器镜像的构建。
当然如果你还想在单机环境下使用 Docker Compose,在 containerd 模式下,我们也可以使用 nerdctl 来兼容该功能。同样我们可以使用 nerdctl compose、nerdctl compose up、nerdctl compose logs、nerdctl compose build、nerdctl compose down 等命令来管理 Compose 服务。这样使用 containerd、nerdctl 结合 buildkit 等工具就完全可以替代 docker 在镜像构建、镜像容器方面的管理功能了。