コンテナの中身を見てみよう

こんにちは、hanhan1978です。この記事はイノベーター・ジャパンAdvent Calendar 2017の6日目の記事です。

コンテナ仮想化が話題ですが、そもそもコンテナって何なのか気になりませんか?
自分は、抽象化された技術をそのまま見過ごして使い続けるのがすごく苦手で、夜も眠れなくなってしまいます...。

というわけで、今回はDockerのコンテナを中身を見てみることで、コンテナについての理解を深めましょう。

Dockerのすごく簡単なおさらい。

Dockerでは、Dockerfileというコンテナの設計図を使ってコンテナイメージを作成します。 Dockerfileの一行目には、 From という命令を使って、元になるコンテナイメージを指定します。

例えば、library/alpine - Docker Hub などは、Docker界隈では非常に有名な軽量Linuxです。
Dockerfile に FROM alipine:latest と記述するとAlpine Linuxをベースイメージとしたコンテナを作成できます。

でも...?

Alpine Linuxは何を元にして出来ているんだろう?遡っていくと一番の元になっているイメージは何なんだろう?

Create a base image | Docker Documentation

Dockerの仕様書に記載がありますが、scratch がDockerの最小単位のベースイメージです。 具体的には、何も含まれていない空のコンテナイメージです。

ここからは、実際に scratch が空なのか?一体コンテナの中身はどうなっているのか?見ていきましょう。

最小限のDockerfile

仕様書には、FROMを省略できそうな記載があるのですが、検証していると細々とエラーが出るので FROM scratchを明示します。 最小限のコマンドとして、MAINTAINER (このDockerfileを管理している人) と、touch blank で予め作成しておいた空ファイルの追加を記述します。

FROM scratch
MAINTAINER hanhan1978
ADD blank /blank

ビルドします。

$ docker build -t test .
Sending build context to Docker daemon  37.89kB
Step 1/3 : FROM scratch
 --->
Step 2/3 : MAINTAINER hanhan1978
 ---> Using cache
 ---> ecd2a0489df2
Step 3/3 : ADD blank /blank
 ---> 6e68d787dc83
Successfully built 6e68d787dc83
Successfully tagged test:latest

イメージのサイズを確認します。

$ docker images test
REPOSITORY      TAG             IMAGE ID        CREATED         SIZE
test            latest          37c8c1eadb08    2 seconds ago   0B

空のベースイメージに、空のファイルを追加したコンテナイメージのサイズは、なんと0Bです。

では、コンテナの中身を見てみましょう。 docker save [タグ名] でコンテナイメージを出力することができます。

$ docker save test > test_image.tar

作成された tarを展開すると、こんなディレクトリ構造になっています。

.
├── 6e68d787dc831bc532a20bd8bdb9fb505a77dc431a14774bba086f24ae13b0eb.json
├── c9aff52f8c22a263c44363c6abb8665b2224a26cf778c5c15da4a4cd746b5eeb
│   ├── VERSION
│   ├── json
│   └── layer.tar
├── manifest.json
└── repositories

殆どがDocker用のmeta情報なのですが、layer.tar というファイルがあります。ここにblankファイルが入っています。 実際に展開してみましょう。

$ tar xvf layer.tar
x blank

blankファイルが出てきました。

つまり、まとめると….

Dockerのコンテナイメージの中身は

  1. Dockerのmeta情報
  2. 自分が追加したコマンド分のイメージレイヤー(tar)

イメージレイヤーは、Dockerfileにコマンドを追加すると、上記の layer.tarが含まれたディレクトリが追加されていきます。

 ├── VERSION
 ├── json
 └── layer.tar

コンテナのサイズは何で決まるのか?

中身が分かると、コンテナのサイズがどのように決まるのかが分かりますね。 つまり、容量の大きいファイルをコンテナに入れればコンテナのサイズは大きくなるし、逆であれば小さくなります。

当たり前のことですが、具体的に中身をみることですごくイメージが掴めやすいですね。 試しに大きいファイルを作ってコンテナに追加してみましょう。

100MBのダミーファイル作成

dd if=/dev/zero of=largefile bs=1M count=100

単純にコンテナイメージに追加します。

FROM scratch
MAINTAINER hanhan1978
ADD largefile /

ビルドします。

$ docker build -t test .
Sending build context to Docker daemon  104.9MB
Step 1/3 : FROM scratch
 --->
Step 2/3 : MAINTAINER hanhan1978
 ---> Using cache
 ---> ecd2a0489df2
Step 3/3 : ADD tempfile /
 ---> 999824e3e166
Successfully built 999824e3e166
Successfully tagged test:latest

イメージサイズを確認します。

$ docker images test
REPOSITORY      TAG             IMAGE ID        CREATED         SIZE
test            latest          999824e3e166    4 seconds ago   105MB

100MBのファイルを追加したら、コンテナのイメージもほぼ100MBになりました。

まとめ

今日は、コンテナの基本ということで、Dockerイメージの中身を具体的に見てみました。

コンテナのイメージサイズが大きいと、pushやpullする際のデータ転送量が大きくなります。コンテナの中身についての基本的な構造を頭に入れた上で、できるだけ小さいイメージを作れると、ネットワークインフラに優しいコンテナイメージになるかと思います。

基本を抑えたら、色んなベースイメージをpullして中身を確認してみて下さい、すごく勉強になりますよ!百聞は一見にしかずです。

明日のアドベントカレンダー担当は、当社マーケティングファームのykkozwさんです。お楽しみに!