#概要
この記事では、アプリケーションコンテナのランタイムであるDockerとrktについて、
2つの大まかな違いを説明し、Dockerとrktそれぞれを使用してコンテナの取得・作成・起動・破棄など基本的なコンテナ操作を実施してみます。
記事全体として「Dockerはある程度知ってるけど、それに比べてrktってどうなんだ?」というトーンで書いています。
Dockerとは
Docker社が開発しているオープンソースのコンテナランタイムです。
コンテナ技術自体は決して新しくはないですが、その使いやすさからある種のコンテナブーム(?)を巻き起こしたともいえるかと思います。
詳しい情報は、ググれば良い記事が山ほど出てくるので割愛します。
rktとは
公式:https://coreos.com/rkt/docs/latest/
CoreOS社が開発している、アプリケーションコンテナのランタイムとなります。
同社が2014年12月に発表したApp Container(appc) Specという標準的なコンテナの仕様を実装したもので、「an alternative to the Docker runtime」として注目を集めています。
現時点での最新バージョンは0.6.1とまだまだプロトタイプの位置づけです。
ちなみにこれまで「rocket」や「Rocket」といった表記が混在していましたが、今後は「rkt」に統一されるらしいです。
Dockerとrktの違い
appcのテーマである「構成の柔軟性」「セキュリティ」「イメージ配布の容易さ」「オープンさ」の切り口で説明してみます。
-
構成の柔軟性
Dockerは、クラウドサーバやクラスタ向けシステムを構築するためののツールや幅広い機能(イメージの作成・動作・アップロード・ダウンロード)が、rootで動作するmonolithicなバイナリで提供されています。
一方でrktにおいては、コンテナをダウンロード、インストール、起動するための全てのツールは統合されてはいますが、それぞれは独立した構成となっています。 -
セキュリティ
Dockerはクラサバ型の設計であり、Dockerクライアントは Dockerデーモンに対して各種コマンドを発行するアーキテクチャとなっています。
Dockerデーモンはroot権限で動作する必要があるため、常にrootプロセスがDockerホスト側で動き続けることになります。
このことを「全てが中央のデーモンを通じて実行されるDockerの処理モデルには、セキュリティと再利用性において根本的な欠陥がある。」とし、root権限デーモン⇔クライアントのアーキテクチャを廃止して新たに生まれたのがrktとなります。 -
コンテナイメージの配布
Dockerは「Docker Hub」や「Docker Private Registry」などのレジストリを通じてコンテナイメージをpull/pushする必要があります。
rktにおいては専用のレジストリは存在せず、WEBの標準的な仕様(HTTPS)を用いてイメージを配布することができます。 -
オープンさ
rktはオープンなコンテナ仕様を実装しています。
コマンドレベルでの細かな違いについては、下記で順を追って見ていきましょう。
環境
coreos(alpha v717.0.0) on vagrant(1.7.2)
インストール
coreosは、アプリケーションをコンテナ上でのみ動作させるように設計されており、
取得したbox(coreos-alpha v717.0.0)ではDocker, rkt共にインストール済みとなっています。
Docker
$ docker -v
Docker version 1.5.0, build a8a31ef-dirty
rkt
$ rkt version
rkt version 0.5.5
appc version 0.5.1+git
ちなみに現時点(2015/6/21)でのrktの最新バージョンは0.6.1となっており、下記の通り最新版をインストールすることもできます。
wget https://github.com/coreos/rkt/releases/download/v0.6.1/rkt-v0.6.1.tar.gz
tar xzvf rkt-v0.6.1.tar.gz
コンテナの取得・作成・起動から破棄まで
コンテナイメージの取得
Docker
Dockerは「Docker Hub」や「Docker Private Registry」などのレジストリを介してイメージを取得・公開することができます。
ここではCentOSの最新イメージを取得しています。
$ docker pull httpd
rkt
rktでは、appcのディスカバリ仕様に従って、インターネット上からコンテナイメージを取得することができます。
ここでは「coreos.com/etcd」というACIを取得する例を示します。
① rkt trust
rktではACIの署名を検証するために公開鍵を取得する必要があります。
$ sudo rkt trust --prefix=coreos.com/etcd
② rkt fetch
次にrkt fetchコマンドでACIの取得、署名の検証を行います。
$ sudo rkt fetch coreos.com/etcd:v2.0.4
なお、Dockerイメージを利用したい場合にDocker Registryからイメージダウンロードし、ACIに変換することもできます。
$ sudo rkt --insecure-skip-verify fetch docker://httpd
※Dockerイメージのsignature verificationはサポートされないため、--insecure-skip-verify
オプションを付けます。
コンテナイメージ一覧
Docker
docker images
コマンドを使用します。
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
httpd latest de94ed779434 5 days ago 161.8 MB
rkt
rkt images
コマンドを使用します。
$ sudo rkt images
KEY APPNAME IMPORTTIME LATEST
sha512-1eba37d9b344b33d272181e176da111ef2fdd4958b88ba4071e56db9ac07cf62 coreos.com/etcd:v2.0.4 2015-06-21 07:38:58.396 +0000 UTC false
sha512-fb95bcc29323607aafcca362bd6beb073c85e34f4cd63db8fe5570b603d33838 httpd:latest 2015-06-21 10:47:48.825 +0000 UTC false
取得した「coreos.com/etcd」と「httpd」イメージが表示されています。
コンテナの起動
Docker
docker run
コマンドを使用します。
-p
オプションでコンテナの80番ポートをホストの8080ポートをマッピングします。
$ docker run -p 8080:80 httpd:latest
ホスト側からコンテナへアクセスしてみます。
$ curl http://localhost:8080/
<html><body><h1>It works!</h1></body></html>
rkt
rktではrkt run
コマンドでイメージ名を指定することでコンテナを起動します。
$ sudo rkt run -local httpd
-local
:ローカルのイメージを利用する
rktのネットワーキングはdockerと異なりデフォルトでホストモードとなっており、ネットワークはホストのものを使用します。
$ curl "http://localhost:80/"
<html><body><h1>It works!</h1></body></html>
プライベートネットワークを利用する場合は、rkt metadata-service
コマンドでMetadata Serviceを起動したのちに--private-net
オプションを使用してコンテナを起動します。
$ sudo rkt metadata-service
後述のrkt list
コマンドでコンテナのIPを確認し、アクセスしてみます。
ここでは試しませんが、イメージのビルド時にポートのエントリを定義しておけば、rkt run
時に--port
オプションを使用することでポートフォワーディングも実現できます。
$ curl "http://172.16.28.3:80"
<html><body><h1>It works!</h1></body></html>
コンテナを落としたいときは、Ctrl-]
を3回押します。
コンテナ一覧
Docker
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
21763385c6bc httpd:latest "httpd-foreground" 5 seconds ago Up 4 seconds 0.0.0.0:8080->80/tcp trusting_yalow
rkt
$ sudo rkt list -full
UUID ACI STATE NETWORKS
26804adf-6394-469d-bb0c-ff7168202368 httpd running default:ip4=172.16.28.3
コンテナの作成(ビルド)
Docker
コンテナの構成内容を記載したDockerfileを指定してdocker build
コマンドでビルドを行います。
① dockerfile作成
下記は簡単な例となりますが、dockerfileは命令 引数
の形式で記載をします。
# ベースイメージ
FROM centos
# 作成者
MAINTAINER sample
# 各種コマンドの実行
RUN yum -y install httpd
# コンテナの実行コマンド
CMD /bin/bash
② ビルド
dockerfileのディレクトリを指定してdocker build
コマンドを実行します。
$ docker build -t myimage ./
③ イメージ確認
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
myimage latest df2ca7e6d2e1 About a minute ago 263.5 MB
rkt
rktのコンテナイメージはACIフォーマットで管理され、appcで提供されているツール「actool」を使用することでビルドできます。
actoolではコンテナの構成内容を記載したJSON形式のMANIFESTファイルとルートファイルシステムを元にACIをビルドします。
① MANIFEST作成
今回は、公式リファレンスを参考にGO言語製サンプルアプリケーションを実行するACIを作成します。
https://github.com/coreos/rkt/blob/master/Documentation/getting-started-guide.md
{
"acKind": "ImageManifest",
"acVersion": "0.6.0",
"name": "myimage",
"labels": [
{"name": "os", "value": "linux"},
{"name": "arch", "value": "amd64"}
],
"app": {
"exec": [
"/bin/hello"
],
"user": "0",
"group": "0"
}
}
② ディレクトリ整備
$ mkdir myimage
$ mkdir myimage/rootfs
$ mkdir myimage/rootfs/bin
# manifest配置
$ mv manifest myimage/
③ GOアプリケーション作成
package main
import (
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
log.Printf("request from %v\n", r.RemoteAddr)
w.Write([]byte("hello\n"))
})
log.Fatal(http.ListenAndServe(":5000", nil))
}
$ CGO_ENABLED=0 GOOS=linux go build -o hello -a -tags netgo -ldflags '-w' .
$ mv hello myimage/rootfs/bin/
④ ビルド
actool build myimage my-app.aci
⑤ コンテナ起動
$ sudo rkt --insecure-skip-verify run myimage.aci
⑥ ホストからアクセス確認
$ curl "http://localhost:5000"
hello
コンテナの削除
Docker
CONATINER IDを指定してdocker rm
コマンドを実行します。
$ docker rm 01fdf4b430b9
01fdf4b430b9
rkt
現時点でコンテナの削除コマンドは存在しないみたいです。
コンテナイメージの削除
Docker
IMAGE IDを指定してdocker rmi
コマンドを実行します。
$ docker rmi de94ed779434
Untagged: httpd:latest
rkt
現時点でコンテナイメージの削除コマンドは存在しないみたいです
まとめ
簡単ではありますが一通りDockerとrktを触ってみました。
冒頭にも述べたとおりrktはプロトタイプの段階であるため、機能的にも使いやすさ的にもDockerにまだまだ劣ると感じています。
実用という点について現段階では多く語れませんが、Dockerのセキュリティ面での問題を解消したというのは言わずもがな、何よりオープンかつシンプルなrktの思想は素敵だと思います。
2015年5月に「Kubernetes」がrktを通じappcサポートすることを明らかにしたこともあるように、今後の可能性に期待したいと思います。