对于用惯了docker cli的用户来说,containerd的命令行工具ctr使用起来不是很顺手,此时别慌,还有另外一个命令行工具项目nerdctl可供我们选择。
nerdctl是一个与docker cli风格兼容的containerd的cli工具。
nerdctl已经作为子项目加入了containerd项目,它的github地址是https://github.com/containerd/nerdctl,而且从最近的nerdctl 0.8开始,nerdctl直接兼容了docker compose的语法(不包含swarm),
这很大提高了直接将containerd作为本地开发、测试和单机容器部署使用的体验。本来k8s后续将不再支持dockershim,docker在k8s社区的地位急剧下降,现在单机直接使用containerd易用性也不断被完善,也许docker的辉煌已经远去了。
实际上nerdctl compose实现的是Compose Specification规范, 这个规范是从自Docker Compose file version 3 specification规范发展而来的。
1.安装nerdctl
containerd 1.5最近刚刚发布,这里先把测试机上的containerd升级到1.5,直接替换containerd的二进制文件,重启containerd的systemd服务即可,升级过程略过。 升级完成后查看客户端和服务端版本均已经是1.5.0:
ctr version
Client:
Version: v1.5.0
Revision: 8c906ff108ac28da23f69cc7b74f8e7a470d1df0
Go version: go1.16.3
Server:
Version: v1.5.0
Revision: 8c906ff108ac28da23f69cc7b74f8e7a470d1df0
UUID: dee82270-b4b4-429c-befa-45df1421da7e注意在安装nerdctl之前,需要确认安装了它的依赖组件(runc、containerd、cni),containerd和cni的详细安装步骤可以参考本系列文章第2节和第3节中的内容。
安装nerdctl:
wget https://github.com/containerd/nerdctl/releases/download/v0.8.1/nerdctl-0.8.1-linux-amd64.tar.gz
tar -zxvf nerdctl-0.8.1-linux-amd64.tar.gz nerdctl && mv nerdctl /usr/local/containerd/bin/
ln -s /usr/local/containerd/bin/nerdctl /usr/local/bin/nerdctl打印一下版本信息:
nerdctl version
Client:
Version: v0.8.1
Git commit: e1601447477c38ceb46c9c88418af399f79b1d6a
Server:
containerd:
Version: v1.5.0
Revision: 8c906ff108ac28da23f69cc7b74f8e7a470d1df02.nerdctl初体验
查看镜像:
nerdctl images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis alpine3.13 f9577ac6e68c 11 days ago 10.4 MiB启动一个redis容器:
nerdctl run -d --name redis redis:alpine3.13
nerdctl ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
709665b06ab1 docker.io/library/redis:alpine3.13 "docker-entrypoint.s…" 28 seconds ago Up redis进入容器内部:
nerdctl exec -it redis sh
/data # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 1a:84:4b:bb:1f:43 brd ff:ff:ff:ff:ff:ff
inet 10.4.0.4/24 brd 10.4.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::1884:4bff:febb:1f43/64 scope link tentative dadfailed
valid_lft forever preferred_lft forever查看宿主机上的网桥和veth对设备:
ls /var/lib/cni/networks/bridge/
10.4.0.4 last_reserved_ip.0 lock
ip addr
......
16: nerdctl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
link/ether 3e:92:4a:37:cb:d3 brd ff:ff:ff:ff:ff:ff
inet 10.4.0.1/24 brd 10.4.0.255 scope global nerdctl0
valid_lft forever preferred_lft forever
inet6 fe80::3c92:4aff:fe37:cbd3/64 scope link
valid_lft forever preferred_lft forever
19: veth98611773@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master nerdctl0 state UP
link/ether 2e:cd:71:38:3d:7b brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::2ccd:71ff:fe38:3d7b/64 scope link
valid_lft forever preferred_lft forever和docker一样,nerdctl也有一个子命令network:
nerdctl network ls
NETWORK ID NAME FILE
0 bridge
host
none可以看一下默认的bridge网络的cni配置:
[
{
"CNI": {
"cniVersion": "0.4.0",
"name": "bridge",
"nerdctlID": 0,
"plugins": [
{
"type": "bridge",
"bridge": "nerdctl0",
"isGateway": true,
"ipMasq": true,
"hairpinMode": true,
"ipam": {
"type": "host-local",
"routes": [
{
"dst": "0.0.0.0/0"
}
],
"ranges": [
[
{
"subnet": "10.4.0.0/24",
"gateway": "10.4.0.1"
}
]
]
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
},
{
"type": "firewall"
},
{
"type": "tuning"
}
]
},
"NerdctlID": 0
}
]可以看出nertctl启动的容器的网络的背后实际上仍然是CNI在工作。
nerctl run命令在启动一个容器时,可以通过--net指定容器连接到一个网络,取值可以是bridge、host、或none,默认是bridge。所以宿主机上出现了nerdctl0网桥和eth98611773@if3。
3.nerdctl兼容docker compose
这里编写一个用于测试的docker-compose.yml文件:
version: '3'
services:
db:
image: postgres:10.1
environment:
- POSTGRES_USER=miniflux
- POSTGRES_PASSWORD=secret
volumes:
- /home/miniflux/miniflux-db:/var/lib/postgresql/data
db-migrate:
image: miniflux/miniflux:2.0.29
command: ["/usr/bin/miniflux", "-migrate"]
depends_on:
- db
environment:
- DATABASE_URL=postgres://miniflux:secret@db/miniflux?sslmode=disable
miniflux:
image: miniflux/miniflux:2.0.29
ports:
- "8080:8080"
depends_on:
- db-migrate
environment:
- DATABASE_URL=postgres://miniflux:secret@db/miniflux?sslmode=disableminiflux是一个开源的RSS阅读器,主要有两个服务组成miniflux web服务和postgres数据库,可以部署Miniflux作为我们自己的RSS服务。 上面的docker compose文件之前已经使用docker-compose在docker上部署过,这里我们实验一下nerdctl在containerd上部署。
在宿主机上创建挂载出来的数据目录:
cd /home
mkdir miniflux
cd miniflux
mkdir miniflux-db使用nerdctl执行compose命令:
nerdctl compose -f docker-compose.yml up -d
INFO[0000] Creating network miniflux_default
INFO[0000] Ensuring image postgres:10.1
INFO[0000] Ensuring image miniflux/miniflux:latest
INFO[0000] Creating container miniflux_miniflux_1
INFO[0000] Creating container miniflux_db_1nerdctl ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
219d71b12daa docker.io/miniflux/miniflux:2.0.29 "/usr/bin/miniflux" 6 minutes ago Up 0.0.0.0:8080->8080/tcp miniflux_miniflux_1
3b5275fdb361 docker.io/miniflux/miniflux:2.0.29 "/usr/bin/miniflux -…" 6 minutes ago Exited (1) 6 minutes ago miniflux_db-migrate_1
540239bdd876 docker.io/library/postgres:10.1 "docker-entrypoint.s…" 6 minutes ago Up miniflux_db_1注:实际使用nerdctl compose启动容器时,因为postgres启动比较慢,而compose里的
depends_on只是描述container启动后就认为依赖OK了,所以可能会出现miniflux_db-migrate_1和miniflux_miniflux_1无法启动的情况。 此时,手动按顺序执行nerdctl start miniflux_db-migrate_1 && nerdctl logs miniflux_db-migrate_1和nerdctl start miniflux_miniflux_1 && nerdctl logs miniflux_miniflux_1最终确保miniflux_miniflux_1和miniflux_db_1都进入up状态即可。
创建admin用户:
nerdctl exec -it <container-name> /usr/bin/miniflux -create-admin
Enter Username: admin
Enter Password:部署成功后可以使用http://ip:8080访问。
总结
可以看出nerdctl的使用方式和docker cli几乎一致,在启动容器和管理容器方面,从docker过渡到使用nerdctl+containerd几乎没有任何学习成本。 有了nerdctl,单机玩耍containerd不再是梦。