Posted at

Docker の学習 ~ runC を使ったコンテナの起動

More than 3 years have passed since last update.

新しいコンテナランタイムである runC を使ってみたので、手順をまとめます。


runC とは?

runC とは Docker社が発表した新しいコンテナランタイム(CLIツール)。今までの Docker は、Docker サーバーがデーモンとして Linux ホストに常駐し、Docker クライアント(docker コマンド)はそれに接続して操作するという形態だった。

runC ではデーモンが不要になり、runC という CLI ツールだけでコンテナの起動が可能になった。コンテナは、runC の子プロセスとして起動される。


検証環境の準備

いつもの通り、AWS EC2上の Amazon Linux インスタンスで検証してみる。まずインスタンスの起動し、ログインして必要なパッケージ(Google Go、git)をインストールする。

$ sudo yum install -y golang git

# Go のバージョンは 1.4.2だった。
$ go version
go version go1.4.2 linux/amd64

# GOPATH の設定
$ mkdir $HOME/go
$ export GOPATH=$HOME/go


runC のコンパイルとインストール

runC はまだ鋭意開発中なので、パッケージからインストールするのではなく、ソースコードからコンパイルする必要がある。

# 作業用ディレクトリの作成

$ mkdir -p $GOPATH/src/github.com/opencontainers
$ cd $GOPATH/src/github.com/opencontainers

# runC のソースをクローン
$ git clone https://github.com/opencontainers/runc

# コンパイル & インストール
$ cd runc
$ make
$ sudo make install

動作確認してみる。

$ runc help

NAME:
runc - Open Container Project runtime

runc is a command line client for running applications packaged according to the Open Container Format (OCF) and is a compliant implementation of the Open Container Project specification.
(以下略…)


コンテナ起動のための準備


コンテナ用ディレクトリの作成

現時点の runC はコンテナを起動する際に、Docker イメージからではなく、イメージに含まれるファイルが展開されたディレクトリから起動する必要がある(っぽい)。このコンテナ用ディレクトリは、今までの Docker Engine を使うと簡単に作成できる。

以下の例では、~/test/centos をコンテナ用ディレクトリとしている。

# Docker のインストールとデーモンの開始

$ sudo yum install docker -y
$ sudo service docker start

# Docker イメージの Pull
$ sudo docker pull centos

# コンテナの起動
$ sudo docker run -d --name dummy centos /bin/bash

# コンテナ用ディレクトリの作成
$ mkdir -p ~/test/centos
$ cd ~/test/centos

# コンテナの中身を tar ファイルにエクスポートする
$ sudo docker export -o centos.tar dummy

# エクスポートした tar を展開する。
$ tar xf centos.tar

# コンテナ用ディレクトリの中身はこんな感じ。
$ ls ~/test/centos/
bin dev home lib64 media opt root sbin sys usr
centos.tar etc lib lost+found mnt proc run srv tmp var

もう、起動したコンテナや tar は不要なので削除してよい。Dockerのデーモンも停止していい。

$ sudo docker stop dummy

$ sudo docker rm dummy
$ rm centos.tar
$ sudo service docker stop


config.json の作成

runC は、コンテナの定義情報が書かれたJSONファイルに従いコンテナを作成する。デフォルトでは、カレントディレクトリにある config.json というファイルが読み込まれる。

この config.json は runc spec コマンドを使うと簡単に作成できるようだが(※1)、今回は中身を確認するためにも手作業で用意した。

(※1) https://runc.io/ を参照。

cd ~/test

vi config.json

以下のようなJSONを記述する。とはいえ、変更が必要な個所は root/path くらい。

ただし、仕様がまだ固まってないようで今後変わる可能性があるため要注意。

{

"version": "pre-draft",
"platform": {
"os": "linux",
"arch": "amd64"
},
"process": {
"terminal": true,
"user": {
"uid": 0,
"gid": 0,
"additionalGids": null
},
"args": [
"sh"
],
"env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm"
],
"cwd": ""
},
"root": {
"path": "/home/ec2-user/test/centos",
"readonly": true
},
"hostname": "my-host",
"mounts": [
{
"type": "proc",
"source": "proc",
"destination": "/proc",
"options": ""
},
{
"type": "tmpfs",
"source": "tmpfs",
"destination": "/dev",
"options": "nosuid,strictatime,mode=755,size=65536k"
},
{
"type": "devpts",
"source": "devpts",
"destination": "/dev/pts",
"options": "nosuid,noexec,newinstance,ptmxmode=0666,mode=0620,gid=5"
},
{
"type": "tmpfs",
"source": "shm",
"destination": "/dev/shm",
"options": "nosuid,noexec,nodev,mode=1777,size=65536k"
},
{
"type": "mqueue",
"source": "mqueue",
"destination": "/dev/mqueue",
"options": "nosuid,noexec,nodev"
},
{
"type": "sysfs",
"source": "sysfs",
"destination": "/sys",
"options": "nosuid,noexec,nodev"
}
],
"linux": {
"uidMappings": null,
"gidMappings": null,
"rlimits": null,
"systemProperties": null,
"resources": {
"disableOOMKiller": false,
"memory": {
"limit": 0,
"reservation": 0,
"swap": 0,
"kernel": 0
},
"cpu": {
"shares": 0,
"quota": 0,
"period": 0,
"realtimeRuntime": 0,
"realtimePeriod": 0,
"cpus": "",
"mems": ""
},
"blockIO": {
"blkioWeight": 0,
"blkioWeightDevice": "",
"blkioThrottleReadBpsDevice": "",
"blkioThrottleWriteBpsDevice": "",
"blkioThrottleReadIopsDevice": "",
"blkioThrottleWriteIopsDevice": ""
},
"hugepageLimits": null,
"network": {
"classId": "",
"priorities": null
}
},
"namespaces": [
{
"type": "process",
"path": ""
},
{
"type": "network",
"path": ""
},
{
"type": "ipc",
"path": ""
},
{
"type": "uts",
"path": ""
},
{
"type": "mount",
"path": ""
}
],
"capabilities": [
"AUDIT_WRITE",
"KILL",
"NET_BIND_SERVICE"
],
"devices": [
"null",
"random",
"full",
"tty",
"zero",
"urandom"
]
}
}


コンテナの起動

あとは、runC コマンドを実行するだけ。カレントディレクトリにある config.json を読み込んで、コンテナを起動してくれる。

$ cd ~/test

$ sudo /usr/local/bin/runc
sh-4.2# hostname
my-host
sh-4.2# ps
PID TTY TIME CMD
1 ? 00:00:00 sh
9 ? 00:00:00 ps


参考サイト

Github runc

runC Official Site

Getting Started with runC