重学容器04: containerd的高阶命令行工具nerdctl
2021-05-06
对于用惯了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:
1ctr version
2Client:
3 Version: v1.5.0
4 Revision: 8c906ff108ac28da23f69cc7b74f8e7a470d1df0
5 Go version: go1.16.3
6
7Server:
8 Version: v1.5.0
9 Revision: 8c906ff108ac28da23f69cc7b74f8e7a470d1df0
10 UUID: dee82270-b4b4-429c-befa-45df1421da7e
注意在安装nerdctl之前,需要确认安装了它的依赖组件(runc、containerd、cni),containerd和cni的详细安装步骤可以参考本系列文章第2节和第3节中的内容。
安装nerdctl:
1wget https://github.com/containerd/nerdctl/releases/download/v0.8.1/nerdctl-0.8.1-linux-amd64.tar.gz
2tar -zxvf nerdctl-0.8.1-linux-amd64.tar.gz nerdctl && mv nerdctl /usr/local/containerd/bin/
3ln -s /usr/local/containerd/bin/nerdctl /usr/local/bin/nerdctl
打印一下版本信息:
1nerdctl version
2Client:
3 Version: v0.8.1
4 Git commit: e1601447477c38ceb46c9c88418af399f79b1d6a
5
6Server:
7 containerd:
8 Version: v1.5.0
9 Revision: 8c906ff108ac28da23f69cc7b74f8e7a470d1df0
2.nerdctl初体验 #
查看镜像:
1nerdctl images
2REPOSITORY TAG IMAGE ID CREATED SIZE
3redis alpine3.13 f9577ac6e68c 11 days ago 10.4 MiB
启动一个redis容器:
1nerdctl run -d --name redis redis:alpine3.13
2
3nerdctl ps
4CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5709665b06ab1 docker.io/library/redis:alpine3.13 "docker-entrypoint.s…" 28 seconds ago Up redis
进入容器内部:
1nerdctl exec -it redis sh
2/data # ip addr
31: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
4 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
5 inet 127.0.0.1/8 scope host lo
6 valid_lft forever preferred_lft forever
7 inet6 ::1/128 scope host
8 valid_lft forever preferred_lft forever
93: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
10 link/ether 1a:84:4b:bb:1f:43 brd ff:ff:ff:ff:ff:ff
11 inet 10.4.0.4/24 brd 10.4.0.255 scope global eth0
12 valid_lft forever preferred_lft forever
13 inet6 fe80::1884:4bff:febb:1f43/64 scope link tentative dadfailed
14 valid_lft forever preferred_lft forever
查看宿主机上的网桥和veth对设备:
1ls /var/lib/cni/networks/bridge/
210.4.0.4 last_reserved_ip.0 lock
3
4ip addr
5......
616: nerdctl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
7 link/ether 3e:92:4a:37:cb:d3 brd ff:ff:ff:ff:ff:ff
8 inet 10.4.0.1/24 brd 10.4.0.255 scope global nerdctl0
9 valid_lft forever preferred_lft forever
10 inet6 fe80::3c92:4aff:fe37:cbd3/64 scope link
11 valid_lft forever preferred_lft forever
1219: veth98611773@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master nerdctl0 state UP
13 link/ether 2e:cd:71:38:3d:7b brd ff:ff:ff:ff:ff:ff link-netnsid 0
14 inet6 fe80::2ccd:71ff:fe38:3d7b/64 scope link
15 valid_lft forever preferred_lft forever
和docker一样,nerdctl也有一个子命令network:
1nerdctl network ls
2NETWORK ID NAME FILE
30 bridge
4 host
5 none
可以看一下默认的bridge网络的cni配置:
1[
2 {
3 "CNI": {
4 "cniVersion": "0.4.0",
5 "name": "bridge",
6 "nerdctlID": 0,
7 "plugins": [
8 {
9 "type": "bridge",
10 "bridge": "nerdctl0",
11 "isGateway": true,
12 "ipMasq": true,
13 "hairpinMode": true,
14 "ipam": {
15 "type": "host-local",
16 "routes": [
17 {
18 "dst": "0.0.0.0/0"
19 }
20 ],
21 "ranges": [
22 [
23 {
24 "subnet": "10.4.0.0/24",
25 "gateway": "10.4.0.1"
26 }
27 ]
28 ]
29 }
30 },
31 {
32 "type": "portmap",
33 "capabilities": {
34 "portMappings": true
35 }
36 },
37 {
38 "type": "firewall"
39 },
40 {
41 "type": "tuning"
42 }
43 ]
44 },
45 "NerdctlID": 0
46 }
47]
可以看出nertctl启动的容器的网络的背后实际上仍然是CNI在工作。
nerctl run
命令在启动一个容器时,可以通过--net
指定容器连接到一个网络,取值可以是bridge、host、或none
,默认是bridge
。所以宿主机上出现了nerdctl0网桥和eth98611773@if3。
3.nerdctl兼容docker compose #
这里编写一个用于测试的docker-compose.yml文件:
1version: '3'
2services:
3 db:
4 image: postgres:10.1
5 environment:
6 - POSTGRES_USER=miniflux
7 - POSTGRES_PASSWORD=secret
8 volumes:
9 - /home/miniflux/miniflux-db:/var/lib/postgresql/data
10 db-migrate:
11 image: miniflux/miniflux:2.0.29
12 command: ["/usr/bin/miniflux", "-migrate"]
13 depends_on:
14 - db
15 environment:
16 - DATABASE_URL=postgres://miniflux:secret@db/miniflux?sslmode=disable
17 miniflux:
18 image: miniflux/miniflux:2.0.29
19 ports:
20 - "8080:8080"
21 depends_on:
22 - db-migrate
23 environment:
24 - DATABASE_URL=postgres://miniflux:secret@db/miniflux?sslmode=disable
miniflux是一个开源的RSS阅读器,主要有两个服务组成miniflux web服务和postgres数据库,可以部署Miniflux作为我们自己的RSS服务。 上面的docker compose文件之前已经使用docker-compose在docker上部署过,这里我们实验一下nerdctl在containerd上部署。
在宿主机上创建挂载出来的数据目录:
1cd /home
2mkdir miniflux
3cd miniflux
4mkdir miniflux-db
使用nerdctl执行compose命令:
1nerdctl compose -f docker-compose.yml up -d
2INFO[0000] Creating network miniflux_default
3INFO[0000] Ensuring image postgres:10.1
4INFO[0000] Ensuring image miniflux/miniflux:latest
5INFO[0000] Creating container miniflux_miniflux_1
6INFO[0000] Creating container miniflux_db_1
1nerdctl ps -a
2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3219d71b12daa docker.io/miniflux/miniflux:2.0.29 "/usr/bin/miniflux" 6 minutes ago Up 0.0.0.0:8080->8080/tcp miniflux_miniflux_1
43b5275fdb361 docker.io/miniflux/miniflux:2.0.29 "/usr/bin/miniflux -…" 6 minutes ago Exited (1) 6 minutes ago miniflux_db-migrate_1
5540239bdd876 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用户:
1nerdctl exec -it <container-name> /usr/bin/miniflux -create-admin
2Enter Username: admin
3Enter Password:
部署成功后可以使用http://ip:8080
访问。
总结 #
可以看出nerdctl的使用方式和docker cli几乎一致,在启动容器和管理容器方面,从docker过渡到使用nerdctl+containerd几乎没有任何学习成本。 有了nerdctl,单机玩耍containerd不再是梦。