はじめに
仮想化は使いたいアプリケーションだけでなく OS も含めてまるごと動かす仕組みです。 これでは、ゲスト OS とホスト OS が同じ Linux であればカーネルなどを重複してロードすることになり無駄にメモリを消費してしまいます。
OS のカーネルはホストのものをそのまま使いますが、アプリケーションから見て自由に使える OS 環境があるというのがコンテナです。 アプリケーションがなにをしても全体が壊れない、他へ影響がない箱をイメージです。
Mac 上では コンテナ は動かないので、例えば Docker for Mac では Linux を内部で立ち上げています。
コンテナを支える技術
コンテナを実現するための Linux カーネルの機能にコントロールグループと名前空間があります。
コントロールグループ cgroups
これらの使用量とアクセスを制限できます。
名前空間 namespace
- プロセス ID
- ネットワーク(インターフェース、ルーティングテーブル、ソケット等)
- マウント(ファイルシステム)
- UTS(ホスト名)
- IPC(セマフォ、MQ、共有メモリなどのプロセス間通信)
- ユーザー(UID,GID)
これらの名前空間を分離できます。 名前空間を分離すると、親となるホスト OS のリソースの許可された一部しか見えなくなり、コンテナが独立してるように見えます。 まるで、自分以外いない世界になります。
コンテナを作ってみた
Docker は Go で書かれており、コアとなるライブラリとしてlibcontainer
が使われています。
libcontainer(リブコンテナ)は Go 言語のネイティブな実装であり、名前空間・cgroup・機能・ファイルシステムへのアクセス管理を持つコンテナを作成します。コンテナを作成後、コンテナに対してライフサイクル上の追加操作を可能にします。http://docs.docker.jp/v1.11/engine/reference/glossary.html#libcontainer
Mac でコンテナが動かないので動作環境も Docker で立てました。 Mac上にDocker(Linux環境)があり、 Docker(Linux環境)上で自作コンテナを動かします。
このリポジトリで作成しました。 github.com
main.go
はlibcontainer
でコンテナを作るコードです。
libcontainer
のREADMEやテストコードを参考にしました。
1. 自作コンテナでのベースイメージを準備します
$ docker pull alpine $ docker run --name alpine alpine $ docker export alpine > alpine.tar $ mkdir rootfs $ tar -C rootfs -xvf alpine.tar
2. DockerでLinux環境を作ります
Macでは自作コンテナは動きません。
$ docker build -t orenocontainer . $ docker run --privileged -it orenocontainer /bin/bash
以下のDockerfileを書きました。
# Dockerfile
FROM golang:1.14
WORKDIR /go/src/github.com/kotaroooo0/orenocontainer
COPY main.go ./
COPY rootfs ./rootfs
RUN go get -v .
RUN go build -o orenocontainer main.go
3. Docker上のLinux環境で自作コンテナを動かします
Goで書いた自作コンテナを起動します。
# Dockerコンテナ内 $ orenocontainer /bin/sh: 0: can\'t access tty; job control turned off # 自作コンテナ内 $ go /bin/sh: 7: go: not found $ hostname 83409d06ecab (TODO: これをconfigで設定したtestingに表示できるようにしたい) $ exit (Dokerコンテナに戻る)
自作コンテナのホストであるDockerではgo
コマンドが使えましたが、自作コンテナ内では使えなくなっています。
これは名前空間を分離したことにより実現されました。
残念な点として、hostname
した際にDockerコンテナと同じホスト名が表示されてしまいました。
ここは、main.go
で定義したホスト名(testing)が表示されてほしかったです。
exit
でDockerからホスト(Mac)に戻れるように、exit
コマンドで自作コンテナからDockerに戻ることができます。
おわりに
Dockerでも使われているlibcontainer
を使って、コンテナ自作をしてみました。
hostname
で期待通りの動作をすることはできませんでした。
今後また改善していけたら良いなと思います。
また、Macでコンテナを開発するの厳しいなと感じました。