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 在镜像构建、镜像容器方面的管理功能了。