Runc 简介
RunC 是什么?
RunC 是一个轻量级的工具,它是用来运行容器的,只用来做这一件事,并且这一件事要做好。我们可以认为它就是个命令行小工具,可以不用通过 docker 引擎,直接运行容器。事实上,runC 是标准化的产物,它根据 OCI 标准来创建和运行容器。而 OCI(Open Container Initiative)组织,旨在围绕容器格式和运行时制定一个开放的工业化标准。
安装 runC
RunC 是用 golang 创建的项目,因此编译它之前需要在本地安装 golang 的开发环境。Golang 的安装请参考《Golang 入门 : 打造开发环境》一文,这里不再赘述。
安装 libseccomp-dev
RunC 默认的编译配置是支持 seccomp 的,所以我们需要先安装 libseccomp-dev:
$ sudo apt install libseccomp-dev
seccomp 的全称为 secure computing mode,即安全计算模型,这是 Linux 内核提供的功能。我们可以通过它来限制容器中进程的行为。关于 seccomp 的更多内容,请参考 Seccomp security profiles for Docker。
获取 runC 的代码
先创建 $GOPATH/src/github.com 目录:
$ mkdir -p $HOME/go/src/github.com
通过 go get 命令就可以从 github 上下载到 runC 的代码,但是要保证事先安装了 git:
$ go get github.com/opencontainers/runc
然后进入 $HOME/go/src/github.com/opencontainers/runc 目录,并 checkout 最新的稳定状态的代码 tag v1.0.0-rc5:
$ cd $HOME/go/src/github.com/opencontainers/runc
$ git checkout v1.0.0-rc5
查看代码当前的状态:
$ git status

v1.0.0-rc5 是当前最新的版本。
编译并安装
$ make
$ sudo make install

如上图所示,runC 被安装在了 /usr/local/sbin/runc 目录。
可以通过 -v 选项查看一下版本号:
$ runc -v

至此,runC 就算是安装成功了。
准备 OCI bundle
RunC 是运行容器的运行时,它负责利用符合标准的文件等资源运行容器,但是它不包含 docker 那样的镜像管理功能。所以要用 runC 运行容器,我们先得准备好容器的文件系统。所谓的 OCI bundle 就是指容器的文件系统和一个 config.json 文件。有了容器的文件系统后我们可以通过 runc spec 命令来生成 config.json 文件。使用 docker 可轻松的生成容器的文件系统,因为 runC 本来就是 docker 贡献给社区的嘛!
下面我们准备一个运行 busybox 容器所需的文件系统:
$ docker pull busybox
$ mkdir -p /tmp/mycontainer/rootfs
$ cd /tmp/mycontainer
$ docker export $(docker create busybox) | tar -C rootfs -xvf -
现在 rootfs 目录下就是 busybox 镜像的文件系统,然后生成 config.json 文件:
$ runc spec

如果直接使用生成的 config.json,接下来的演示不会太流畅,所以简单起见,我们稍微修改一下刚刚生成的 config.json 文件。就是把 "terminal": true 改为 false,把 "args": ["sh"] 改为 "args": ["sleep", "30"]:

理解容器状态转移
在运行 busybox 容器前让我们先来看看 OCI 都定义了哪几种容器状态,以及这些状态是如何转移的。先看容器的状态:
- creating:使用 create 命令创建容器,这个过程称为创建中。
- created:容器已经创建出来,但是还没有运行,表示镜像文件和配置没有错误,容器能够在当前平台上运行。
- running:容器里面的进程处于运行状态,正在执行用户设定的任务。
- stopped:容器运行完成,或者运行出错,或者 stop 命令之后,容器处于暂停状态。这个状态,容器还有很多信息保存在平台中,并没有完全被删除。
- paused:暂停容器中的所有进程,可以使用 resume 命令恢复这些进程的执行。
下图则是对容器不同状态间转移的一个粗略描述:

RunC 命令
要想了解 runC 都能干什么,最好是通过它提供的命令来操作容器。下面是笔者整理的 runC 命令的主要使用场景。
查看帮助
$ runc -h
查看子命令的帮助
$ runc help subcommand
使用 create 命令创建容器
进入到 /tmp/mycontainer 目录中:
$ cd /tmp/mycontainer
然后创建名为 mybusybox 的容器:
$ sudo runc create mybusybox
使用 list 命令查看当前存在的容器
$ sudo runc list

使用 state 命令查看容器的状态
$ sudo runc state mybusybox

注意图中的 "status": "created",当通过 create 成功创建了容器后,容器的状态就是 "created"。
使用 ps 命令看看容器内运行的进程
$ sudo runc ps mybusybox

此时 mybusybox 容器内有一个名为 init 的进程在运行。
使用 start 命令执行容器中定义的任务
$ sudo runc start
使用 start 命令启动容器后,让我们再用 ps 命令看看容器内运行了什么进程:

此时我们在 config.json 中定义的 sleep 进程在运行。再用 state 命令看看容器此时的状态,此时已经变成了 running!
使用 exec 命令在容器中执行命令
通过 exec 命令我们可以在处于 created 状态和 running 状态的容器中执行命令:
$ sudo runc exec mybusybox ls

当容器中的用户任务结束后,容器会变成 stopped 状态,这时就不能再通过 exec 执行其它的命令了。
使用 delete 命令删除容器
我们可以通过 delete 命令删除容器,当然,一般情况下是删除 stopped 状态的容器:
$ sudo runc delete mybusybox
使用 run 命令创建并运行容器
就像 docker run 命令一样,它会创建容器并运行容器中的命令:
$ sudo runc run mybusybox
当容器中的命令退出后容器随即被删除。
使用 kill 命令停止容器中的任务
如果要停止一个容器中正在运行的任务,可以使用 kill 命令:
$ sudo runc kill mybusybox
默认它会优雅的结束容器中的进程,但是碰到特殊情况,你就得使用终极信号 9:
$ sudo runc kill mybusybox
使用 pause 命令暂停容器中的所有进程
我们先启动容器 mybusybox,然后用 pause 命令暂停它:
$ sudo runc pause mybusybox

执行 pause 命令后,容器的状态由 running 变成了 paused。然后我们再通过 resume 命令恢复容器中进程的执行:
$ sudo runc resume mybusybox

此时容器的状态又恢复到了 running。
使用 events 命令获取容器的资源使用情况
events 命令能够向我们报告容器事件及其资源占用的统计信息:
$ sudo runc events mybusybox

rootless containers
前面我们运行的所有命令都是以 root 权限执行的。能不能以普通用户的权限运行容器呢?答案是可以的,并被称为 rootless。要想以 rootless 的方式运行容器,需要我们在生成容器的配置文件时就为 spec 命令指定 rootless 参数:
$ runc spec --rootless
并且在运行容器时通过 --root 参数指定一个存放容器状态的路径:
$ runc --root /tmp/runc run mybusybox
容器的热迁移操作
RunC 支持容器的热迁移操作,所谓热迁移就是将一个容器进行 checkpoint 操作,并获得一系列文件,使用这一系列文件可以在本机或者其他主机上进行容器的 restore 工作。这也是 checkpoint 和 restore 两个命令存在的原因。热迁移属于比较复杂的操作,目前 runC 使用了 CRIU 作为热迁移的工具。RunC 主要是调用 CRIU(Checkpoint and Restore in Userspace)来完成热迁移操作。CIRU 负责冻结进程,并将作为一系列文件存储在硬盘上。并负责使用这些文件还原这个被冻结的进程。
总结
RunC 作为标准化容器运行时的一个实现目前已经被 docker 内置为默认的容器运行时。相信随着 runC 自身的成熟和完善会有越来越多的大厂把 runC 作为默认的容器运行时。
参考:
Runc Github
OCI和runc容器标准化和docker
OCI标准和runC原理解读
Runc 简介的更多相关文章
- Containerd 简介
我们可以把 docker 抽象为下图所示的结构(此图来自互联网): 从图中可以看出,docker 对容器的管理和操作基本都是通过 containerd 完成的. 那么,containerd 是什么呢? ...
- 从 docker 到 runC
笔者在前文<RunC 简介>和<Containerd 简介>中分别介绍了 runC 和 containerd.本文我们将结合 docker 中的其它组件探索 docker 是如 ...
- Docker的主要组件
Docker 的主要组件 安装 docker ,其实是安装了 docker 客户端.dockerd 等一系列的组件,其中比较重要的有下面几个. Docker CLI(docker)docker 程序是 ...
- Docker 简介,入门
1.简介 Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 AUFS 类的 Union FS 等技术,对进程进行 ...
- Docker简介与安装配置
目录 Docker简介 什么是Docker 为啥要用容器 Docker Engine Docker架构说明 Docker安装 Docker版本介绍 Ubuntu安装docker-ce CentOS7安 ...
- 深入理解Docker容器执行引擎runC
1 简介 根据官方的定义:runC是一个根据OCI标准创建并运行容器的CLI tool. Docker就是基于runC创建的,简单地说,runC就是docker中最为核心的部分,容器的创建,运行,销毁 ...
- Docker 容器简介与部署
关于Docker容器技术 参考文献:<docker 从入门到精通> Docker容器简介 Docker的构想是要实现 "Build,Ship and Run Any App,An ...
- DOCKER学习_001:Docker简介
一 Docker简介 1.1 docker由来 Docker的英文翻译是“码头工人”,即搬运工,它搬运的东西就是我们常说的集装箱Container,Container里面装的是任意类型的App.我们的 ...
- 架构师修炼之微服务部署 - Docker简介
Docker简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器或Windows 机器上,也可以实现虚拟化,容器是 ...
随机推荐
- Linux系统的shell是什么
shell是用户和Linux操作系统之间的接口.Linux中有多种shell,其中缺省使用的是Bash.本章讲述了shell的工作原理,shell的种类,shell的一般操作及Bash的特性. 什么是 ...
- C语言实现ifconfig获取网卡接收和发送流量统计
在Windows下我们可以利用ipconfig命令获取网卡的相关信息,在Linux下命令是ifconfig 我们可以获取的信息更为丰富,其中包括网卡接收和发送的流量,用C语言实现这个命令并不是一件简单 ...
- 程序员的视角:java GC
GC(Garbage Collection 垃圾回收)的概念随着 java 的流行而被人们所熟知. 实际 GC 最早起源于20世纪60年代的 LISP 语言,是一种自动的内存管理机制. GC 要解决的 ...
- JavaScript进阶(四)js字符串转换成数字的三种方法
js字符串转换成数字的三种方法 在js读取文本框或者其它表单数据的时候获得的值是字符串类型的,例如两个文本框a和b,如果获得a的value值为11,b的value值为9 ,那么a.value要小于b. ...
- Dynamics CRM2011中通过JS脚本方式显示和隐藏ribbon中的自定义按钮
首先该方法不能写在页面的onload中,因为当从子网格返回常规表单的时候ribbon区域会重新加载而常规表单所在的iframe区域是不会被刷新的,所以如果写在onload中的话就控制的不那么完全了,我 ...
- LeetCode之“树”:Validate Binary Search Tree
题目链接 题目要求: Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is ...
- Bookmarkable Pages
Build a Bookmarkable Edit Page with JDeveloper 11g Purpose In this tutorial, you use Oracle JDevel ...
- BMP 转 YUV (BMP2YUV)
本文介绍BMP 转 YUV.其实这是以前"数据压缩"实验课上的内容,前几天有人问我相关的问题,突然发现自己有一段时间没有接触BMP也有些生疏了,因此翻出资料总结一下. BMP文件格 ...
- css3中的布局相关样式
web页面中的布局是指在页面中如何对标题.导航栏.主要内容.脚注.表单等各种构成要素进行合理编辑.在css3之前,主要使用float属性或position属性进行页面中的简单布局,但是也存在一些缺点, ...
- RunTime运行时在iOS中的应用之UITextField占位符placeholder
RunTime运行时机制 runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API. 在我们平时编写的Objective-C代码中, 程序运行过程时, 其实最终 ...