この記事はDocker Advent Calendar 2019の21日目の記事です。
Dockerが内部で使用しているHigh-levelランタイムのcontainerd
をコンテナ内で起動して動かしてみた話です。
コンテナ内で動かす方法に関してはcontainerdのリポジトリにそのやり方が記載されていますが、その通りにやっても私の環境では一部上手くいかなかったのでその解決策も含めて紹介できればと思います。
環境
- OS: ubuntu 16.04
- golang: go1.13
- Docker: 19.03.5
- containerd: v1.3.0-203-g97712c8a 97712c8ad73dd302d5d226e0384b2d86e5de2989
ソースの取得
containerd
を動かすに当たってソースからバイナリを作成するのでローカルにソースを取得しておきます。
contaierd
の他にlow-levelランタイムであるrunc
も今回は一緒にビルドするので合わせて取得します。
取得方法はgo get -u github.com/containerd/containerd
とgo get -u github.com/opencontainers/runc
を実行すればOKです。
Dockerイメージの作成
ソースの取得が終わったら次にcontainerd
を動かすコンテナのDockerイメージを作成します。
containerd
はGo言語を使用して作られているので、Dockerイメージのgolangをベースに、ビルドするのに必要なモジュールをインストールしていきます。
必要なモジュールはB-Tree FileSystem用のbtrfs-tools
とSeccomp用のlibseccomp-dev
の二つです。
FROM golang:latest
RUN apt-get update \
&& apt-get install -y btrfs-tools libseccomp-dev
あとはdocker build -t containerd/build .
でDockerイメージを作成すればコンテナ用のDockerイメージの準備は完了です。
コンテナの起動
上記で作成したDockerイメージを使ってコンテナを起動します。
docker run -it --privileged \
-v /var/lib/containerd \
-v ${GOPATH}/src/github.com/opencontainers/runc:/go/src/github.com/opencontainers/runc \
-v ${GOPATH}/src/github.com/containerd/containerd:/go/src/github.com/containerd/containerd \
-e GOPATH=/go \
-w /go/src/github.com/containerd/containerd containerd/build bash
containerd
の起動には特権が必要になるので--privileged
オプションをつけ、起動に必要なフォルダと上記で取得したソースをマウントした上で起動しています。
そのほかのオプションはGOPATH
の設定とコンテナ起動時のディレクトリを指定しています。
公式のやり方ではbash
ではなくsh
を起動しているのですが、個人的にbash
の方が慣れているので変えています。
ソースのビルド
次はコンテナ内でcontainerd
とrunc
をビルドしていきます。
それぞれMakefile
が用意されているのでそれを利用します。
// containerdのフォルダに移動。
// コンテナ起動時にこのフォルダがカレントディレクトリになっているはずなので実行しなくても大丈夫
$ cd /go/src/github.com/containerd/containerd
$ make && make install
// エラー!
vendor/github.com/containerd/btrfs/btrfs.go:38:25: fatal error: btrfs/ioctl.h: No such file or directory
#include <btrfs/ioctl.h>
^
compilation terminated.
make: *** [bin/containerd] Erreur 2
実はこの状態でビルドするとエラーとなります。containerd
が依存しているcontaienrd/btrfs
というモジュールがあり、そのモジュールからbtrfs
がないと言われるのが原因です。
Dockerイメージを作る際にbtrfs-tools
をインストールしましたが、どうもこれでは駄目なようでbtrfs-tools
の代わりにlibbtrfs-dev
をインストールすればビルドが通りました。
FROM golang:latest
RUN apt-get update \
&& apt-get install -y libbtrfs-dev libseccomp-dev
公式に記載されているやり方と異なるので問題がある可能性もありますが、一旦これでDockerイメージを作成しなおしてコンテナを起動すればビルドは通るようになります。
あとはcontainerd
と同様にrunc
もビルドしてやれば準備完了です。
cd /go/src/github.com/opencontainers/runc
make BUILDTAGS='seccomp apparmor' && make install
containerdの起動
make install
した段階でcontainerd
のバイナリがPATH
の通っているディレクトリに配置されますのでそれを起動すればcontainerd
が動きます。
$ containerd // バックグラウンドで起動したい場合は containerd &
$ INFO[2019-12-21T13:56:32.716026618Z] starting containerd ...
$ INFO[2019-12-21T13:56:32.760340925Z] loading plugin ...
// 以下ログが出力される
これでやっとcontainerd
が動かせました!
あとは好きなようにいじりたおせばOKですね。
まとめ
簡単ですがコンテナ内でcontainerd
を動かすやり方を紹介させてもらいました。
そもそも何故動かそうと思ったかというと、個人的にコンテナランタイムの開発に挑戦していてDocker
で動かしてみたら上手く動かず原因を探っていくとcontainerd
とのやりとりに問題がありそうだという事が分かったので、containerd
を動かして見ようと思ったのがきっかけでした。
ただ起動するだけでなく構成を記述した設定ファイルを渡す事もできるようなので、その辺りも公式に情報があるのでよければそちらも見てみて下さい。