crun是一个快速轻量级、低内存、全功能、符合OCI规范、用于运行容器的Runtime,与runc一样可以用于创建、部署容器,它使用C语言开发。
本文记录手工编译crun以及使用crun创建容器的方法,供后续学习源代码做准备。
关于 git clone 项目代码编译的说明
一般而言,编译crun最好的方法是:
1 | # 第一步,git clone 源代码 |
使用上述方法简单快捷、成功率高。那我们使用官方提供的release包来编译,是否也是如此顺利?
使用release包编译肯定可以成功,但执行make命令时,会提示一个 找不到git-version.h文件 的错误:
1 | src/crun.c:20:10: fatal error: git-version.h: No such file or directory |
所以,只要我们解决了 git-version.h 的生成问题,编译也同样顺利!
git-version.h文件是做什么用的?
我们执行 crun --version
命令时会有 commit 的一行输出,它代表当前代码在git仓库中的版本号,而这个版本号就是出自于git-version.h文件。
git-version.h文件是如何产生的?
我们打开Makefile的模板文件Makefile.am,文件中有这么几行:
可见 git-version.h 文件有两种产生途径:
第一种,如果当前目录中存在 .tarball-git-version.h 文件,直接拷贝重命名生成 git-version.h。
第二种,如果当前目录中没有 .tarball-git-version.h 文件,版本号由git命令从当前仓库中取出,然后写入生成 git-version.h。
而我们下载的release包,比如crun-1.14.4.tar.gz,解压后,它既没有 .tarball-git-version.h 文件,又不是一个有效的git仓库,所以上述两种方法都无法正常生成 git-version.h。
明白上述原因之后,我们来总结下:
clone项目代码的方法很容易生成 git-version.h,而使用release包来编译crun,需要我们按照 git-version.h 的文件内容格式,手工添加 .tarball-git-version.h 文件,然后让make命令顺利执行,生成 git-version.h 文件后,编译成功。
正常 git-version.h 文件的内容格式如下所示:
编译release包>第一步 安装依赖
1 | $ sudo apt-get install -y make cmake git gcc build-essential pkgconf libtool go-md2man autoconf python3 automake \ |
编译release包>第二步 下载源代码
下载crun代码包:
网站地址:https://github.com/containers/crun/releases
从上图可知,我们下载1.14.4版本的发行包,然后得知该版本的commit版本号是:a220ca661ce078f2c37b38c92e66cf66c012d9c1。记下该commit版本号,后续在生成git-version.h文件时,需要使用到。
下载crun依赖的libocispec代码包:
由于libocispec没有打tag或者release包,我们直接下载当前仓库的zip包:
网站地址:https://github.com/containers/libocispec
下载libocispec依赖的image-spec代码包:
网站地址:
https://github.com/opencontainers/image-spec/releases
选择版本后下载,本文使用如下版本:
https://github.com/opencontainers/image-spec/archive/refs/tags/v1.1.0.tar.gz
下载libocispec依赖的runtime-spec代码包:
网站地址:
https://github.com/opencontainers/runtime-spec/releases
选择版本后下载,本文使用如下版本:
https://github.com/opencontainers/runtime-spec/archive/refs/tags/v1.2.0.tar.gz
下载libocispec依赖的yajl代码包:
网站地址:
https://github.com/containers/yajl/tags
选择版本后下载,本文使用如下版本:
https://github.com/containers/yajl/archive/refs/tags/2.1.0.tar.gz
我们下载完代码之后,所有代码包如下所示:
编译release包>第三步 解压源代码
解压crun-1.14.4.tar.gz
1 | $ tar -zxf crun-1.14.4.tar.gz |
解压libocispec-main.zip
1 | $ cd crun-1.14.4/libocispec |
解压image-spec-1.1.0.tar.gz
1 | $ cd crun-1.14.4/libocispec/image-spec |
解压runtime-spec-1.2.0.tar.gz
1 | $ cd crun-1.14.4/libocispec/runtime-spec |
解压yajl-2.1.0.tar.gz
1 | $ cd crun-1.14.4/libocispec/yajl |
编译release包>第四步 生成.version、.tarball-version和.tarball-git-version.h文件
1 | $ cd crun-1.14.4 |
上述命令中我们指定GIT_VERSION为 a220ca661ce078f2c37b38c92e66cf66c012d9c1,该字段的值在上节下载crun源代码时,我们提及过获取的方法。它代表当前包在git中的commit版本号。
当然该字段,我们也可以随意填写,字段值只是用于提示,并没有特别重要的意义,随意填写不影响可执行程序的使用。
生成过程如下图所示:
编译release包>第五步 生成crun的configure文件
1 | $ cd crun-1.14.4 |
编译release包>第六步 配置生成Makefile以及编译、安装
1 | $ cd crun-1.14.4 |
编译和安装成功之后,我们看下安装目录的结构:
使用crun运行容器
第一步,生成config.json
使用如下命令:
1 | $ crun spec |
执行过程如下图所示:
第二步,生成镜像根文件系统,我们使用busybox的docker镜像。
使用如下命令:
1 | $ mkdir rootfs |
执行过程如下图所示:
第三步,启动镜像
使用如下命令:
1 | $ sudo crun run demo-container_with_crun |
执行过程如下图所示:
保持终端不关闭以及当前容器不退出,我们在另外一个终端上查看下当前机器上的容器运行情况。
使用如下命令:
1 | $ sudo crun list |
执行过程如下图所示: