Docker イメージのレイヤーの理解を深めるために、Dockerホストのコンソール上で牛にMooと言わせるだけのコンテナを動かし、そのコンテナを例にとってDockerイメージのレイヤーの状態を整理してみました。
いまいちDockerイメージのレイヤーの概念がよく分からないという方に参考になれば幸いです。 (※各ファイルのディレクトリの構成は、現在ストレージドライバの標準になっているoverlay2を使った場合の例です。)
サンプルのDockerコンテナで実現すること
牛に"Moo"と言わせるだけです。
Dockerfileを作る
Dockerホストの任意のディレクトリ(ここで は cowsay
としました)に、以下のようなDockerfileを作ってみます。
FROM debian:buster RUN apt-get update && apt-get install -y cowsay
debian:buster
のイメージをDocker hubから取得- 牛を表示するアプリケーション
cowsay
をインストール
というシンプルなDockerfileです。
Dockerfileをビルドし、イメージを作る
Dockerfileがあるディレクトリ内に移動し、作ったDockerfileをビルドし、イメージを作ります。
$ cd cowsay $ docker build -t test/cowsay . Sending build context to Docker daemon 2.048kB Step 1/2 : FROM debian:buster ---> 6d6b00c22231 Step 2/2 : RUN apt-get update && apt-get install -y cowsay ---> Using cache ---> 5b2abe87f6d2 Successfully built 5b2abe87f6d2 Successfully tagged test/cowsay:latest
まずは docker images
を実行して、test/cowsay
のDockerイメージが出来ていることを確認します。
$ docker images test/cowsay:latest REPOSITORY TAG IMAGE ID CREATED SIZE test/cowsay latest 20961704943e 16 seconds ago 179MB
次に docker history
を実行してイメージの状態を確認してみます。2つのイメージレイヤーが出来ていることを確認できました。
$docker history test/cowsay:latest IMAGE CREATED CREATED BY SIZE COMMENT 5b2abe87f6d2 27 seconds ago /bin/sh -c apt-get update && apt-get install… 64.5MB 6d6b00c22231 6 days ago /bin/sh -c #(nop) CMD ["bash"] 0B <missing> 6 days ago /bin/sh -c #(nop) ADD file:6014cd9d7466825f8… 114MB
この2つのイメージレイヤーはそれぞれDockerホストの異なるディレクトリにファイルの差分が保存されます。
- 上の方のイメージレイヤー(IMAGE: 5b2abe87f6d2)は、牛が表示されるアプリケーション
cowsay
をインストールした後のレイヤー - 下の方のイメージレイヤ(IMAGE: 6d6b00c22231)は、ベースイメージ
debian:buster
をPULLした後のレイヤー
です。
それぞれのレイヤーの差分がDockerホスト上のどのディレクトリは保存されるかは、コンテナが出来た後docker container inspect
というコマンド( 後述)を実行して確認できます。
Dockerホスト上のディレクトリを参照すると、各レイヤーはそれぞれ差分の情報しかもっておらず
- 上の方のイメージレイヤー(IMAGE: 5b2abe87f6d2)には、アプリケーション
cowsay
があるが、PULLしたベースイメージdebian:buster
のファイルはない - 下の方のイメージレイヤ(IMAGE: 6d6b00c22231)は、ベースイメージ
debian:buster
のファイルはあるがcowsay
はない
ということがわかります。
この例はシンプルなDockerfileなのでレイヤーが少ないですが、Dockerfileが大きくなるほど、レイヤーは多くなり、複数のレイヤーの差分を重ねることで1つのDockerイメージができます。
コンテナを触ってみる
bashで入る① (cowsayがあるイメージからコンテナを作る)
イメージからコンテナを作り、 bash
で入ってみます。この際、docker historyの上の方のイメージ(5b2abe87f6d2: cowsayインストール後にできたイメージ)を指定してみます。
$ docker run -it 5b2abe87f6d2 /bin/bash root@b2b28d1d223f:/# ls /usr/games/cowsay /usr/games/cowsay
docker historyの上の方のイメージ(5b2abe87f6d2)を指定すると、下のイメージの差分も入っていることを確認できます。( bash
コマンドは、ベースイメージdebian:buster
の中にあります。)
コンテナに入る際、以下のように名前でイメージを指定しても結果は同じです。
$ docker run -it test/cowsay /bin/bash
bashで入る② (cowsayがないイメージからコンテナを作る)
次に、docker historyの下の方のイメージ(6d6b00c22231: cowsayインストール前のイメージ)を指定してみます。
$ docker run -it 6d6b00c22231 /bin/bash root@4f9452a93ebd:/# ls /usr/games/cowsay ls: cannot access '/usr/games/cowsay': No such file or directory
これは cowsay
インストール前なので、 cowsay
の実行ファイルがないことが確認できます
Dockerホストから cowsay
を実行してみます
$ docker run 6d6b00c22231 /usr/games/cowsay "Moo" _____ < Moo > ----- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
cowsay
インストール前のイメージを指定するとエラーが返ります。
$ docker run 6d6b00c22231 /usr/games/cowsay "Moo" docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "/usr/games/cowsay": stat /usr/games/cowsay: no such file or directory: unknown. ERRO[0000] error waiting for container: context canceled
Dockerホスト上のディレクトリの場所の確認方法
docker container inspect
にコンテナ名を指定すると関連するファイルの場所を確認できます。
$ docker container ls -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c23fee232a48 test/cowsay "/usr/games/cowsay M…" 8 hours ago Exited (0) 8 hours ago awesome_banach
ドキュメントを参照すると、イメージレイヤのファイルはLowerDirに保存されるようです。
$ $ docker container inspect awesome_banach -f "{{json .GraphDriver.Data}}" | jq . { "LowerDir": "/var/lib/docker/overlay2/4e1a74ac2ac471b3484c196250a7e1be8f36eb8dc64ade4fcc4bdec1e4a95010-init/diff:/var/lib/docker/overlay2/d867fc751ea99450c01330ebdac487c1f12db47f35eeab6c628683a3f762310c/diff:/var/lib/docker/overlay2/6431aa52a32ab412806f379a4830b6cc059c3fb5f9380c8d5b8df298ae005e5b/diff", "MergedDir": "/var/lib/docker/overlay2/4e1a74ac2ac471b3484c196250a7e1be8f36eb8dc64ade4fcc4bdec1e4a95010/merged", "UpperDir": "/var/lib/docker/overlay2/4e1a74ac2ac471b3484c196250a7e1be8f36eb8dc64ade4fcc4bdec1e4a95010/diff", "WorkDir": "/var/lib/docker/overlay2/4e1a74ac2ac471b3484c196250a7e1be8f36eb8dc64ade4fcc4bdec1e4a95010/work" }