containerd/nerdctl - 一个开源、免费的Docker的替代品

2021年8月31日,Docker公司更改了收费策略,简而言之就是对个人和小公司不收费,对大公司收费。

那么,是时候开始试一下 containerd + lima这个开源、免费的Docker替代品。

什么是containerd?

containerd是一个标准化的容器运行时,可以被其他系统很方便的集成。正是由于这个原因,containerd也成为了Kubernetes的默认容器运行时。

但是在containerd的目标聚焦在和其他系统集成,所以它的默认命令行工具(crictl)也不是很好用,和docker也不兼容。

后来,nttlabs贡献了一个名为nerdctl的containerd客户端,可以兼容docker命令行工具。于是我们就可以使用nerdctl来作为docker的替代品了。

nerdctl不仅与docker兼容,而且还支持了更多的功能:

  • 支持containerd的命名空间查看,nerdctl不仅可以管理Docker容器,也可以直接管理本地的的Kubernetes pod
  • 支持将Docker Image Manifest镜像转换为OCI镜像、estargz镜像
  • 支持OCIcrypt(镜像加密)

什么是lima?

containerd要在macOS上使用,需要安装虚拟机、然后在虚拟机配置containerd,这个过程很浪费时间。

所以,lima项目简化了这个过程。

lima会启动一个虚拟机,然后在虚拟机中安装containerd,并自动配置虚拟机的文件共享,网络等。

lima相比Docker for Desktop Mac,也有一些优势:

  • 内置lazy pulling支持(基于stargz)
  • 额外支持ARM on Intel,Intel on ARM(基于QEMU)
  • 可以自定义虚拟机发行版(默认是Ubuntu)

上手试用

对于Intel Mac,直接使用brew安装:

安装lima
1
$ brew install lima

如果是ARM Mac,需要手动安装特定版本的QEMU

在开始使用之前,需要创建一个虚拟机,默认的虚拟机名字是default:

启动lima虚拟机
1
2
3
4
$ limactl start
? Creating an instance "default" Open an editor to override the configuration
...
INFO[0207] READY. Run `lima` to open the shell.

可以将虚拟机定义中,$HOME目录的writable值改成true,方便在容器中把文件写回到宿主机上

然后就可以用lima uname -a来确认虚拟机已经运行成功:

确认lima虚拟机已经启动
1
2
$ lima uname -a
Linux lima-default 5.11.0-31-generic #33-Ubuntu SMP Wed Aug 11 13:19:04 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

不要忘了我们的目标是为了替换docker,所以需要设置命令别名:

设置docker别名
1
2
3
$ alias docker='limactl shell default nerdctl "$@"'
$ docker --version
nerdctl version 0.11.2

构建和运行镜像

首先,创建文件~/lima-test/Dockerfile, 内容如下:

lima-test的Dockerfile
1
2
FROM nginx
RUN echo "hello lima" > /usr/share/nginx/html/index.html

然后基于上述文件构建镜像:

构建lima-test镜像
1
$ docker build -t lima-test .

构建完成后,使用上述镜像运行容器:

启动limat-test容器
1
$ docker run -d -p 127.0.0.1:8080:80 lima-test

可以看到,nerdctl已经兼容了docker的绝大部分操作了,完全可以取代docker了。

一些有用的配置

  1. 把nerdctl别名写成shell脚本,替换docker命令:
创建一个shell脚本,替换docker命令
1
2
3
4
5
$ cat > ~/bin/docker <<EOF
#!/bin/sh
limactl shell default nerdctl "\$@"
EOF
$ chmod a+x ~/bin/docker

这样,就可以直接在命令行直接使用基于nerdctl的docker命令了。

  1. 自动补全配置

~/.bash_profile添加如下几行:

自动补全配置
1
2
source <(docker completion bash)
complete -o bashdefault -o default -o nospace -F _nerdctl_bash_autocomplete docker

这样就可以自动补全docker命令行了:

自动补全效果
1
2
3
4
5
$ docker <tab>
build container help inspect login network pull run system version
commit events image internal logout pause push save tag volume
completion exec images kill logs port rm start top wait
compose h info load namespace ps rmi stop unpause

总结

最近在自己的机器上使用了这套替代方案,基本上可以替代docker了。但是仍然发现了一些隐藏的缺陷,比如lima和nerdctl的参数解析有点问题,lima的变量传递有点问题等等。我也提交了一些PR来修复这些问题。

另外,社区中也有很多类似的项目,比如podman,minikube等。但是podman和minikube都没有采用Kubernetes默认运行时containerd。在本地开发,当然最好使用和生产环境一样的配置,所以我还是更加推荐containerd和lima。


最后,再谈一谈Docker和容器。

这可能已经是Docker公司第二次提醒我们 Docker 不等于容器了。

就像Kubernetes需要一个中立的容器标准,所以OCI出现了;容器客户端也需要一个中立的标准和参考实现,目前containerd/nerdctl+lima是一个比较合适的方案,值得关注这两个项目的长期发展。

containerd/nerdctl - 一个开源、免费的Docker的替代品

https://robberphex.com/nerdctl-a-docker-alternative/

作者

Robert Lu

发布于

2021-09-20

许可协议

评论