/var/lib/docker/imagesと/var/lib/docker/overlay2を彷徨った話

/var/lib/docker/の下にあるDockerイメージ関係のファイルを色々見たってだけの話です。目的としてはDockerイメージがどのように管理されているのかの理解を深めたいってことと、どんなファイルがどこにあるのかを把握したかったことでしょうか。

目次

環境

Docker for MacMoby OSにscreenコマンドで入ってます。環境の情報は以下。

/ # docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 0
Server Version: 17.06.1-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file

(省略)

/ # 

保存されているDockerイメージは一度全て削除しました。また、使用しているStorage Driverはoverlay2(OverlayFS)です。

docker pull

※Dockerイメージのアップデートによって下記と同様の結果を得られない可能性があります

docker pullはDockerイメージをダウンロードしてくるコマンドと思われがち(?)な気がしますが、実際は「ローカル環境にないレイヤ(イメージの差分)をダウンロードするコマンド」です。とりあえずhttpd:2.4というイメージをdocker pullでローカルに保存します。

/ # docker pull httpd:2.4
2.4: Pulling from library/httpd
ad74af05f5a2: Pull complete 
3d839585b9c7: Pull complete 
cf157792586a: Pull complete 
c620105f0566: Pull complete 
830b826a2e13: Pull complete 
ec2eb5743536: Pull complete 
eb53f3c09897: Pull complete 
Digest: sha256:5b35d13089db73df620f4c198f5a4bfa56b8fe45a0364f343df9a26d874fef6c
Status: Downloaded newer image for httpd:2.4
/ #

次にcassandra:3をpullしましょう。

/ # docker pull cassandra:3
3: Pulling from library/cassandra
ad74af05f5a2: Already exists 
3d839585b9c7: Already exists 
a87bb16b5ac4: Pull complete 
1d7e4aef1e06: Pull complete 
d60628bada83: Pull complete 
923dfced70a8: Pull complete 
2dcb172a5d25: Pull complete 
1fdf88044a29: Pull complete 
3b51736e19e9: Pull complete 
2fe35cc8fdbb: Pull complete 
8af4ba731cbc: Pull complete 
Digest: sha256:11405c2afbe5e1d7487b72eb6df1b0791d3f3ac644959427e311ba5d51272bd1
Status: Downloaded newer image for cassandra:3
/ # 

Already existsとなっているレイヤが2つあるのが確認できます。

ここでhttpd:2.4のDockerfileと、cassandra:3のDockerfileを見てみましょう。両方ともdebian:jessie-backportsというイメージを使用して作られていることがわかります。

Already existsとなっている2つのレイヤはdebian:jessie-backportsで使われているレイヤであり、cassandraとhttpdで共通していることがわかります。そしてcassandra:3のpull時にすでにこれらのレイヤはローカルに存在するので、レジストリからダウンロードをしていません。

docker buildによるDockerイメージの作成

httpd:2.4を使って新たにDockerイメージを作成します。今回はtestというイメージを作成しました。

/ # mkdir work; cd work
/work # cat > Dockerfile <<EOF
> FROM httpd:2.4
> RUN echo aaa
> ADD bbb /
> EOF
/work # echo "bbb" > bbb
/work # docker build -t test .
Sending build context to Docker daemon  3.072kB
Step 1/3 : FROM httpd:2.4
 ---> e74fcb59d25b
Step 2/3 : RUN echo aaa
 ---> Running in c0a96a2abd2b
aaa
 ---> 5a611d17ce49
Removing intermediate container c0a96a2abd2b
Step 3/3 : ADD bbb /
 ---> a3af767eee5b
Removing intermediate container e5057599e7b0
Successfully built a3af767eee5b
Successfully tagged test:latest
/work # docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test                latest              a3af767eee5b        21 seconds ago      177MB
cassandra           3                   17c6f78ff576        6 days ago          385MB
httpd               2.4                 e74fcb59d25b        6 weeks ago         177MB
/work # 

DockerイメージのレイヤはDockerfileに書かれた"リソースの状態に変化を与える命令"の数だけ増えていきます。今回はRUN echo aaaADD bbbという命令を実行しています。echoコマンドはリソースの状態を変化させませんが、ADDは新たなファイルを追加します。 よってtestはhttpd:2.4のレイヤに新たなレイヤを1つ乗っけたDockerイメージになりました。

ただし、このRUN echo aaaによって、a3af767eee5b(test)の親となる5a611d17ce49というイメージの情報は作成されました。5a611d17ce49はレイヤの構造としてはe74fcb59d25b(httpd:2.4)と同じですが、異なるイメージIDです。

何を言ってるかわかんない人はdocker historyを実行すると理解できるんじゃないでしょう。

/ # docker history test
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
a3af767eee5b        2 minutes ago        /bin/sh -c #(nop) ADD file:506bbbe260d22ea...   4B                  
5a611d17ce49        2 minutes ago        /bin/sh -c echo aaa                             0B                  
e74fcb59d25b        6 weeks ago         /bin/sh -c #(nop)  CMD ["httpd-foreground"]     0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop)  EXPOSE 80/tcp                0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop) COPY file:761e313354b918...   133B                
<missing>           6 weeks ago         /bin/sh -c set -x  && buildDeps="   bzip2 ...   9.72MB              
<missing>           6 weeks ago         /bin/sh -c #(nop)  ENV HTTPD_ASC_FALLBACK_...   0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop)  ENV HTTPD_BZ2_FALLBACK_...   0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop)  ENV HTTPD_ASC_URL=https...   0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop)  ENV HTTPD_BZ2_URL=https...   0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop)  ENV HTTPD_SHA1=699e4e91...   0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop)  ENV HTTPD_VERSION=2.4.27     0B                  
<missing>           6 weeks ago         /bin/sh -c apt-get update  && apt-get inst...   44.2MB              
<missing>           6 weeks ago         /bin/sh -c {   echo 'deb http://deb.debian...   161B                
<missing>           6 weeks ago         /bin/sh -c #(nop)  ENV OPENSSL_VERSION=1.0...   0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop)  ENV NGHTTP2_VERSION=1.1...   0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop) WORKDIR /usr/local/apache2    0B                  
<missing>           6 weeks ago         /bin/sh -c mkdir -p "$HTTPD_PREFIX"  && ch...   0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop)  ENV PATH=/usr/local/apa...   0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop)  ENV HTTPD_PREFIX=/usr/l...   0B                  
<missing>           6 weeks ago         /bin/sh -c echo 'deb http://deb.debian.org...   55B                 
<missing>           6 weeks ago         /bin/sh -c #(nop)  CMD ["bash"]                 0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop) ADD file:a023a99f7d01868...   123MB      
/ # 

ちなみにDockerイメージのレイヤの数は、docker historyを実行したときに表示されるSIZEが0でないイメージの数と同じです。

docker inspectによるイメージの情報の取得

docker inspectはイメージやコンテナの様々な情報を表示するコマンドです。3つのイメージに対して実行し、結果を表にまとめました。

httpd:2.4 test cassandra:3
Id e74fcb59d25b a3af767eee5b 17c6f78ff576
Parent 5a611d17ce49
GraphDriver.Data.LowerDir 2db33dc1bcf8 2db33dc1bcf8 2db33dc1bcf8
92a02a0fd573 92a02a0fd573 92a02a0fd573
bf8eeee84ee1 bf8eeee84ee1 2f5f62573954
3907c84a2e8c 3907c84a2e8c 039eb2914846
9d7c5f5db931 9d7c5f5db931 f2045875c7ca
abddae19644c abddae19644c 0daf771f959a
849ba3b8deea 897896a0d4b6
8803b3ac7c28
6f0b9ede8868
908b9aa83622
GraphDriver.Data.MergedDir 849ba3b8deea 94289abd0b2d a497601c2f47
GraphDriver.Data.UpperDir 849ba3b8deea 94289abd0b2d a497601c2f47
GraphDriver.Data.WorkDir 849ba3b8deea 94289abd0b2d a497601c2f47
RootFS.Layers 2c40c66f7667 2c40c66f7667 2c40c66f7667
4552698f75ca 4552698f75ca 4552698f75ca
d0d2ea1af79e d0d2ea1af79e c15ba818508c
1cec7f0b11da 1cec7f0b11da e24d47802b79
485676c94e85 485676c94e85 1d83810d7a13
b1154a5677c9 b1154a5677c9 df00dc937d70
8dcb04aec53f 8dcb04aec53f 6de82d4abef4
2fae8ef74840 db42563f880d
fe10c6340d87
ac348eb6c295
c6f65dc602de
  • id
    • イメージのID
  • Parent
    • イメージを作る際に元となったイメージ(DockerfileのFROMで指定したイメージ)
    • pullしてきたイメージのParentは空になってる
      • docker historyで<missing>になっていたら空になる
      • 昔は空にならなかった?*1
  • GraphDriver.Data.*
    • よくわからんがoverlayfsに関係するものみたいです
    • LowerDirはDockerイメージを構成するもの
    • その他はコンテナに関係するもの?
  • RootFS.Layers
    • 文字通りの解釈をすると「ルートファイルシステムのレイヤ」
    • 各列のセルの個数とハッシュ値に注目するとGraphDriver.Data.LowerDirと対応関係がある気がします

/var/lib/dockerの探索

/var/lib/docker(Docker Root)はDocker関係の色々なデータが保存されている場所です。

/ # cd /var/lib/docker
/var/lib/docker # tree -L 1
.
├── containers
├── image
├── network
├── overlay2
├── plugins
├── swarm
├── tmp
├── trust
└── volumes

9 directories, 0 files
/var/lib/docker # 

主にDockerイメージに関係するのはimageとoverlay2のディレクトリです。

/var/lib/docker/image の探索

/var/lib/docker/imageには以下のようなディレクトリとファイルがあります

/var/lib/docker/image # tree -L 2
.
└── overlay2
    ├── distribution
    ├── imagedb
    ├── layerdb
    └── repositories.json

4 directories, 1 file
/var/lib/docker/image #

repositories.json

まずrepositories.jsonを表示してみます。

/var/lib/docker/image/overlay2 # cat repositories.json | jq
{
  "Repositories": {
    "cassandra": {
      "cassandra:3": "sha256:17c6f78ff576daa2f84e94eee62ca6a0d1bf4c35e41246a9ba0179b1cffc8000",
      "cassandra@sha256:11405c2afbe5e1d7487b72eb6df1b0791d3f3ac644959427e311ba5d51272bd1": "sha256:17c6f78ff576daa2f84e94eee62ca6a0d1bf4c35e41246a9ba0179b1cffc8000"
    },
    "httpd": {
      "httpd:2.4": "sha256:e74fcb59d25bdf03adcc8d89bcda8ae9456d2041c557c973072085708814e5c7",
      "httpd@sha256:5b35d13089db73df620f4c198f5a4bfa56b8fe45a0364f343df9a26d874fef6c": "sha256:e74fcb59d25bdf03adcc8d89bcda8ae9456d2041c557c973072085708814e5c7"
    },
    "test": {
      "test:latest": "sha256:a3af767eee5b9e96b12623e60c4bd71aad6613bbf127b0bb13e039dafa28e16a"
    }
  }
}
/var/lib/docker/image/overlay2 #

ここにはイメージのタグとIDの対応が書かれています。「cassandra@sha256:11405c2afbe5e…」というのはRepositoryIDで、イメージのリポジトリを表すハッシュ値のようです。たぶんDockerレジストリからpullした時に設定されるものでしょう。

distribution

/var/lib/docker/image/overlay2/distribution # tree -L 2
.
├── diffid-by-digest
│   └── sha256
└── v2metadata-by-diffid
    └── sha256

4 directories, 0 files
/var/lib/docker/image/overlay2/distribution # 

双方のsha256というディレクトリの下には数百個のファイルが置いてありました。よくわかんないですがDocker Registry(Docker Distribution)に関係するメタデータとかを保存してあるディレクトリのようです。ちらっとmoby/distributionのソースを読んで見たりもしましたが、わかったのはその程度。

diffid-by-digest/sha256のディレクトリの下のファイルにはハッシュ値が書いてあります。たとえばこんな感じです。

/var/lib/docker/image/overlay2/distribution/diffid-by-digest/sha256 # echo $(cat f814b22b783e01a2e2dce50c55554ca2777bb4f56098398d96d4532aa7642e1f)
sha256:b6a88c37a096ae33a00249244c5c057f18b996a65bd44c5033fbc8482c465cfc
/var/lib/docker/image/overlay2/distribution/diffid-by-digest/sha256 # 

b6a88c37a096ae33a002…というハッシュ値はv2metadata-by-diffid/sha256の下にファイル名として存在していました。その内容は以下です。

/var/lib/docker/image/overlay2/distribution/v2metadata-by-diffid/sha256 # cat b6
a88c37a096ae33a00249244c5c057f18b996a65bd44c5033fbc8482c465cfc | jq
[
  {
    "Digest": "sha256:f814b22b783e01a2e2dce50c55554ca2777bb4f56098398d96d4532aa7642e1f",
    "SourceRepository": "docker.io/library/mariadb",
    "HMAC": ""
  }
]
/var/lib/docker/image/overlay2/distribution/v2metadata-by-diffid/sha256 # 

なんかぼくが結構昔にpullした覚えのあるイメージのリポジトリの名前がでてきました。docker pullの履歴…でしょうか。

imagedb

/var/lib/docker/image/overlay2/imagedb # tree -L 4
.
├── content
│   └── sha256
│       ├── 17c6f78ff576daa2f84e94eee62ca6a0d1bf4c35e41246a9ba0179b1cffc8000
│       ├── 5a611d17ce49bcb851f8888f76bfaabedd01e6f72a3285542c0c4bd428412240
│       ├── a3af767eee5b9e96b12623e60c4bd71aad6613bbf127b0bb13e039dafa28e16a
│       ├── e74fcb59d25bdf03adcc8d89bcda8ae9456d2041c557c973072085708814e5c7
│       └── temp
└── metadata
    └── sha256
        ├── 5a611d17ce49bcb851f8888f76bfaabedd01e6f72a3285542c0c4bd428412240
        │   └── parent
        └── a3af767eee5b9e96b12623e60c4bd71aad6613bbf127b0bb13e039dafa28e16a
            └── parent

6 directories, 7 files
/var/lib/docker/image/overlay2/imagedb # 

おっ!見たことあるハッシュ値が出てきましたね。

まずcontent/sha256の下にあるハッシュ値のファイルはイメージのIDのハッシュ値と一致します。5a611d17ce49…ってファイルはtestイメージのParentのIDと一致します。これらのファイルはjson形式のファイルで、docker inspectのコマンドを実行した時のようなものが表示されました。まぁイメージの情報が記載されたファイルと言っていいのかなと思います。

特に興味深かったのは"history"という項目で、ここではいつどのようなコマンドでレイヤが作られたのかが全てわかります。

...
  "history": [
    {
      "created": "2017-07-24T16:51:25.302466408Z",
      "created_by": "/bin/sh -c #(nop) ADD file:a023a99f7d01868b164d63bfaf8aabc7f271659c69939c3854f041f5a3217428 in / "
    },
    {
      "created": "2017-07-24T16:51:25.711083944Z",
      "created_by": "/bin/sh -c #(nop)  CMD [\"bash\"]",
      "empty_layer": true
    },
    {
      "created": "2017-07-24T16:51:28.195514863Z",
      "created_by": "/bin/sh -c echo 'deb http://deb.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/backports.list"
    },
...

tempディレクトリは空でした。

metadata/sha256ディレクトリにはハッシュ値の名前のディレクトリの下にparentというファイルが存在します。1つずつその内容を見てみましょう。

/var/lib/docker/image/overlay2/imagedb/metadata/sha256 # echo $(cat 5a611d17ce49bcb851f8888f76bfaabedd01e6f72a3285542c0c4bd428412240/parent )
sha256:e74fcb59d25bdf03adcc8d89bcda8ae9456d2041c557c973072085708814e5c7
/var/lib/docker/image/overlay2/imagedb/metadata/sha256 # echo $(cat a3af767eee5b9e96b12623e60c4bd71aad6613bbf127b0bb13e039dafa28e16a/parent )
sha256:5a611d17ce49bcb851f8888f76bfaabedd01e6f72a3285542c0c4bd428412240
/var/lib/docker/image/overlay2/imagedb/metadata/sha256 # 

これは単純にイメージの親子関係を示したものな気がします。なんとなく「a3…の親は5a…で、5a…の親はe7…」というのを表してる気がします。ていうかdocker historyを実行すればわかるんじゃないか。

/var/lib/docker/image/overlay2/imagedb/metadata/sha256 # docker history test
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
a3af767eee5b        5 hours ago         /bin/sh -c #(nop) ADD file:506bbbe260d22ea...   4B                  
5a611d17ce49        5 hours ago         /bin/sh -c echo aaa                             0B                  
e74fcb59d25b        6 weeks ago         /bin/sh -c #(nop)  CMD ["httpd-foreground"]     0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop)  EXPOSE 80/tcp                0B                  
<missing>           6 weeks ago         /bin/sh -c #(nop) COPY file:761e313354b918...   133B    
...

推測は当たってましたね。

layerdb

/var/lib/docker/image/overlay2/layerdb # tree -L 2
.
├── mounts
├── sha256
│   ├── 0b5f5b5372687dc3ee654a390291ff3fad4a16453982324c7a1516b5fdad3344
│   ├── 16b24c982e9af95d8901216f85a88a619b388afcdaffafe7fee4dfd297a3cdd2
│   ├── 2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc
│   ├── 307d16ce704ed0b8e116087ee1fba751ee2b37ba9f4ffd0c66bc113290316e58
│   ├── 401d4edd5b986b47951ab29b2eaff57d54b95af3087e03e67948fa65de99043d
│   ├── 45f77e6fb6f40c7ae6d8ab47a2fb68aeb22366daa8203bfce4156a8121341b1b
│   ├── 4965e73361fe8100273897579149913ecb5a8429721656c5c999542adda3abc2
│   ├── 58c80d31b95aece5164c036a124a7c5c9d4a255cd0401243412d2d6a54fe5368
│   ├── 5a850e1dce73e5ee3487cc6db12a7382d8850b7a8cdc48dc4d4c27baba8f3219
│   ├── 68ba39668b7fee407c39a6b62559ffea45fbd53af01b913f59544a01fc341ca7
│   ├── 74baa82fa7b49621f26d837d1946b239eab368714791e47dbc9fef63e808d563
│   ├── ae203f0b5fb6d009c5497b5f38411087d2fa50d0e7c3e7b5a707c8f83d761104
│   ├── bd88d85b29f57a5c4f6f0a32117750257dcb07d0c823e5aafc75b5eb83cacd7e
│   ├── c27aaeeaafc3fa91ad11673c6bd1ded2a6dab88ecf5c0cdb29cb7a800523e2f7
│   ├── cac57b9fa5f9ee5d8f76ead54ce9d3192ebe5ef7e5b42d4977dbccefb0df3799
│   ├── d29fdb354f8c5359ef8fc3eb92bad413be6593a500ccbd536a50386bdb5098ef
│   └── d88f40d9b23524a317ed26592089b884d6f3d1135761233b5b3fa6d175e3b4b2
└── tmp

20 directories, 0 files
/var/lib/docker/image/overlay2/layerdb # 

mountsとtmpというディレクトリは空ですね…。sha256の下にはハッシュ値の名前のディレクトリが17個あります。17ってことは…docker inspectの表のRootFS.Layersの種類の数と一致してますね。

2c40c66f7667…というハッシュ値は、現在保存してある3つのイメージに共通するベースイメージのIDと同じですね。しかし、それ以外のハッシュ値は見たことがありません。とりあえず2c40c66f7667…ディレクトリの下を調べます。

/var/lib/docker/image/overlay2/layerdb/sha256/2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc # ls -l
total 472
-rw-r--r--    1 root     root            64 Sep  8 07:45 cache-id
-rw-r--r--    1 root     root            71 Sep  8 07:45 diff
-rw-r--r--    1 root     root             9 Sep  8 07:45 size
-rw-r--r--    1 root     root        470368 Sep  8 07:45 tar-split.json.gz
/var/lib/docker/image/overlay2/layerdb/sha256/2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc # 

ファイルが4つあって、その内1つはgzipで圧縮されたjsonファイルのようですね。

/var/lib/docker/image/overlay2/layerdb/sha256/2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc # echo $(cat cache-id )
2db33dc1bcf8c874324675de0c9a919ce9f3abbc9cfe947840fa33ea7ef38a8d
/var/lib/docker/image/overlay2/layerdb/sha256/2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc # echo $(cat diff)
sha256:2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc
/var/lib/docker/image/overlay2/layerdb/sha256/2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc # echo $(cat size)
123450406
/var/lib/docker/image/overlay2/layerdb/sha256/2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc # 

うーんよくわからん。他のディレクトリの中も見てみましょう。

/var/lib/docker/image/overlay2/layerdb/sha256/0b5f5b5372687dc3ee654a390291ff3fad4a16453982324c7a1516b5fdad3344 # ls -l
total 20
-rw-r--r--    1 root     root            64 Sep  8 07:45 cache-id
-rw-r--r--    1 root     root            71 Sep  8 07:45 diff
-rw-r--r--    1 root     root            71 Sep  8 07:45 parent
-rw-r--r--    1 root     root             2 Sep  8 07:45 size
-rw-r--r--    1 root     root           381 Sep  8 07:45 tar-split.json.gz
/var/lib/docker/image/overlay2/layerdb/sha256/0b5f5b5372687dc3ee654a390291ff3fad4a16453982324c7a1516b5fdad3344 # echo $(cat cache-id )
92a02a0fd5736b9fb0f2e5daa315bfd56cc753a50f38dcc34cf4c60304159016
/var/lib/docker/image/overlay2/layerdb/sha256/0b5f5b5372687dc3ee654a390291ff3fad4a16453982324c7a1516b5fdad3344 # echo $(cat diff)
sha256:4552698f75ca2ab79d3a88725c9749f3994085abbf462011892b034a5ead2813
/var/lib/docker/image/overlay2/layerdb/sha256/0b5f5b5372687dc3ee654a390291ff3fad4a16453982324c7a1516b5fdad3344 # echo $(cat size)
55
/var/lib/docker/image/overlay2/layerdb/sha256/0b5f5b5372687dc3ee654a390291ff3fad4a16453982324c7a1516b5fdad3344 # echo $(cat parent)
sha256:2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc
/var/lib/docker/image/overlay2/layerdb/sha256/0b5f5b5372687dc3ee654a390291ff3fad4a16453982324c7a1516b5fdad3344 # 

んん!?parentってファイルが現れましたね。もう1つ他のディレクトリの中も…

/var/lib/docker/image/overlay2/layerdb/sha256/16b24c982e9af95d8901216f85a88a619b388afcdaffafe7fee4dfd297a3cdd2 # ls -l
total 20
-rw-r--r--    1 root     root            64 Sep  8 07:47 cache-id
-rw-r--r--    1 root     root            71 Sep  8 07:47 diff
-rw-r--r--    1 root     root            71 Sep  8 07:47 parent
-rw-r--r--    1 root     root             2 Sep  8 07:47 size
/var/lib/docker/image/overlay2/layerdb/sha256/16b24c982e9af95d8901216f85a88a619b388afcdaffafe7fee4dfd297a3cdd2 # echo $(cat cache-id )
0daf771f959a4fb1f987cdce446ad84fbfd4924eaf9ac8558d287cc25f76d32d
/var/lib/docker/image/overlay2/layerdb/sha256/16b24c982e9af95d8901216f85a88a619b388afcdaffafe7fee4dfd297a3cdd2 # echo $(cat diff)
sha256:df00dc937d70bdb82f35892405fcd19420a9c75d6cfa070537c316b7e3327746
/var/lib/docker/image/overlay2/layerdb/sha256/16b24c982e9af95d8901216f85a88a619b388afcdaffafe7fee4dfd297a3cdd2 # echo $(cat size)
85
/var/lib/docker/image/overlay2/layerdb/sha256/16b24c982e9af95d8901216f85a88a619b388afcdaffafe7fee4dfd297a3cdd2 # echo $(cat parent)
sha256:307d16ce704ed0b8e116087ee1fba751ee2b37ba9f4ffd0c66bc113290316e58
/var/lib/docker/image/overlay2/layerdb/sha256/16b24c982e9af95d8901216f85a88a619b388afcdaffafe7fee4dfd297a3cdd2 # 

いろんなハッシュ値見てきて流石に疲れてきました。

sizeはレイヤのサイズが書かれたファイルに間違いないでしょう。cache-idのハッシュ値はGraphDriver.Data.LowerDirのハッシュ値の中に一致するものがあります。diffのファイルのハッシュ値はGraphDriver.Data.LowerDirのハッシュ値に対応するレイヤでしょうか。前にも言いましたがdocker inspectの表を見るとGraphDriver.Data.LowerDirのセルとRootFS.Layersのセルは対応関係があるように見えるんですよね。

parentファイルについては「なるほど、imagedbのparentファイルはイメージの親子関係を示すものでしたが、layerdbのparentファイルはレイヤの親子関係を示すものっぽい…」と言いたかったんですが、307d16ce704e…というハッシュ値は初めて見ました。なんだこりゃ。ていうかディレクトリの名前のハッシュ値の意味もよくわかんないですよね…

さて、スルーしてきたtar-split.jsonなんですが、こいつはクソでかくて内容も意味不明なんですが非常に興味深いファイルでした。解凍してheadで出力してみるとこんな感じになっています。

/var/lib/docker/image/overlay2/layerdb/sha256/2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc # gzip -d tar-split.json.gz 
/var/lib/docker/image/overlay2/layerdb/sha256/2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc # head tar-split.json
{"type":2,"payload":"YmluLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwNDA3NTUAMDAwMDAwMAAwMDAwMDAwADAwMDAwMDAwMDAwADEzMTM0NzYzNDAwADAxMDAyMQAgNQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=","position":0}
{"type":1,"name":"bin/","payload":null,"position":1}
{"type":2,"payload":"YmluL2Jhc2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAxMDA3NTUAMDAwMDAwMAAwMDAwMDAwADAwMDAzNzMyNzcwADEzMDA3NDQ2NTcxADAxMDcxMgAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=","position":2}
{"type":1,"name":"bin/bash","size":1029624,"payload":"Zm7whxqHhHs=","position":3}
{"type":2,"payload":"AAAAAAAAAABiaW4vY2F0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDEwMDc1NQAwMDAwMDAwADAwMDAwMDAAMDAwMDAxNDUzMTAAMTI1MDEwNTM3NzAAMDEwNTE2ACAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVzdGFyADAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAAMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==","position":4}
{"type":1,"name":"bin/cat","size":51912,"payload":"yjb1ezeiycI=","position":5}
{"type":2,"payload":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYmluL2NoYWNsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAxMDA3NTUAMDAwMDAwMAAwMDAwMDAwADAwMDAwMDM0MzQwADEyNDAzMjUyMTQxADAxMTAxMwAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=","position":6}
{"type":1,"name":"bin/chacl","size":14560,"payload":"1nko8F2nz90=","position":7}
{"type":2,"payload":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYmluL2NoZ3JwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAxMDA3NTUAMDAwMDAwMAAwMDAwMDAwADAwMDAwMTY1MjUwADEyNTAxMDUzNzcwADAxMTA1NwAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=","position":8}
{"type":1,"name":"bin/chgrp","size":60072,"payload":"BDG8jvA7tS4=","position":9}
/var/lib/docker/image/overlay2/layerdb/sha256/2c40c66f7667aefbb18f7070cf52fae7abbe9b66e49b4e1fd740544e7ceaebdc # 

「"name"はDockerイメージに格納されているファイルかな〜」とか「"payload"はファイルの内容かな〜」って推測ができます。"position"はtailで確認したところ16517までありました。

調べて見るとこれはtar-splitというもの使用して作られたファイルのようです。tarファイルを逆アセンブルしてjsonのオブジェクトとして分けている???用途はいまいちよくわかってません。

/var/lib/docker/overlay2の探索

overlay2(OverlayFS)についてはDocker技術入門Docker-docs-jaが参考になります。

/var/lib/docker/overlay2 # tree -L 1
.
├── 039eb29148465722868d44cca608f800468b4fee3e17656fefe8c6849ba8a273
├── 0daf771f959a4fb1f987cdce446ad84fbfd4924eaf9ac8558d287cc25f76d32d
├── 2db33dc1bcf8c874324675de0c9a919ce9f3abbc9cfe947840fa33ea7ef38a8d
├── 2f5f62573954383a3198c873dec271ace28a90305417849784783d53e573e04e
├── 3907c84a2e8cea3b5c4f8936769381a9b1c8517e1a102f1c1ca601ef84775658
├── 6f0b9ede88685f011e22f57cdc3128928648a262a26bfbb88ce5a28f991ced5b
├── 849ba3b8deead52bbb555dfd3003da9cc3cf1b5ed947574a945962f615b3288e
├── 8803b3ac7c2854f462495405210e1b37571755ae03a3dd401bc5eedcf0ef9ed1
├── 897896a0d4b68945de1e16fa69a29be337822bf3d9be72f3807fd6c762a19a6d
├── 908b9aa836221d528df4039a8972c78cee8f62362239a340197851441095f270
├── 92a02a0fd5736b9fb0f2e5daa315bfd56cc753a50f38dcc34cf4c60304159016
├── 94289abd0b2d381a14b20a0801cb59f38ebdbb1f61e88f7ab6a0a931b4e46f28
├── 9d7c5f5db93144797926396ab64b3ef9e9af755bb1ae1c374f1bc125ef8d62ee
├── a497601c2f47a3d26189522e10097592728df133d6418ac4b97f575fd1a087fd
├── abddae19644c1d09d312ce1dbe6c1b95815d5f9917cc0ec2fd55b7554bed6813
├── bf8eeee84ee100f366d677e19fbea7680f87ca431f8634f14ce08bf490a013e8
├── f2045875c7cad61ac4f5c694865daa780825b064569835b48857f6fab180fc57
└── l

18 directories, 0 files
/var/lib/docker/overlay2 # 

ディレクトリ内にはGraphDriver.Data.LowerDirで見たハッシュ値ディレクトリがいくつもあり、lという名前のディレクトリも存在します。まず初めにlの中を見ます。

/var/lib/docker/overlay2 # ls -l l
total 68
lrwxrwxrwx    1 root     root            72 Sep  8 07:45 6CJN3N2LQUWFFE5JXD76TSGXJA -> ../2db33dc1bcf8c874324675de0c9a919ce9f3abbc9cfe947840fa33ea7ef38a8d/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:45 7QZA73LSD7ZBNOEM24DB3JYCL7 -> ../849ba3b8deead52bbb555dfd3003da9cc3cf1b5ed947574a945962f615b3288e/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:45 DFYUB2X43MSKOPR6KPWA5NDXZS -> ../abddae19644c1d09d312ce1dbe6c1b95815d5f9917cc0ec2fd55b7554bed6813/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:45 GIS437CEOFWNTOUFLYZ6Y5VXGV -> ../3907c84a2e8cea3b5c4f8936769381a9b1c8517e1a102f1c1ca601ef84775658/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:48 HP2UA5JBG5VRENFVGX2HQPFYO5 -> ../6f0b9ede88685f011e22f57cdc3128928648a262a26bfbb88ce5a28f991ced5b/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:48 IGLBERN35IOHTKT4IHQWN7QU4Y -> ../a497601c2f47a3d26189522e10097592728df133d6418ac4b97f575fd1a087fd/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:45 IW4UTGZLJQFFL7YIJOORJXBOMC -> ../9d7c5f5db93144797926396ab64b3ef9e9af755bb1ae1c374f1bc125ef8d62ee/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:47 KJAF45SHPEBMO7YLF2TXNE7IHJ -> ../f2045875c7cad61ac4f5c694865daa780825b064569835b48857f6fab180fc57/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:48 MG4BLYAE6ANVWDLEITBAF3IQZD -> ../908b9aa836221d528df4039a8972c78cee8f62362239a340197851441095f270/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:47 OOQ3TV5QD5GMPWTBUZ3OVADX66 -> ../897896a0d4b68945de1e16fa69a29be337822bf3d9be72f3807fd6c762a19a6d/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:47 P5LQ54M2LA4RHYIWUTFZ7UWREN -> ../039eb29148465722868d44cca608f800468b4fee3e17656fefe8c6849ba8a273/diff
lrwxrwxrwx    1 root     root            72 Sep  8 10:02 QZL3Z4CKLPVJAKAS2FVQEZV5OY -> ../94289abd0b2d381a14b20a0801cb59f38ebdbb1f61e88f7ab6a0a931b4e46f28/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:47 R6ICSXFWWKVF5COWGMVK6V7FIE -> ../2f5f62573954383a3198c873dec271ace28a90305417849784783d53e573e04e/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:47 ULLIFMMDGK4L7GRHG5K342KB3N -> ../0daf771f959a4fb1f987cdce446ad84fbfd4924eaf9ac8558d287cc25f76d32d/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:45 Z3HSFRAFYXCHT3NTSHGLPXNG5M -> ../bf8eeee84ee100f366d677e19fbea7680f87ca431f8634f14ce08bf490a013e8/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:47 ZABQTUIS3WWBV5IF65IGFTYZ6O -> ../8803b3ac7c2854f462495405210e1b37571755ae03a3dd401bc5eedcf0ef9ed1/diff
lrwxrwxrwx    1 root     root            72 Sep  8 07:45 ZSG73ARDTW3UFT47AW4DJWQFAC -> ../92a02a0fd5736b9fb0f2e5daa315bfd56cc753a50f38dcc34cf4c60304159016/diff
/var/lib/docker/overlay2 # 

ハッシュ値ディレクトリの下のdiffというディレクトリのシンボリックリンクがありました。ファイル名は大文字の英字と数字からなっています。

次にハッシュ値ディレクトリの下を見てみます。試しに039eb2914846572…のディレクトリの中身を表示します。

/var/lib/docker/overlay2/039eb29148465722868d44cca608f800468b4fee3e17656fefe8c6849ba8a273 # ls -l
total 20
drwxr-xr-x    6 root     root          4096 Sep  8 07:47 diff
-rw-r--r--    1 root     root            26 Sep  8 07:47 link
-rw-r--r--    1 root     root            86 Sep  8 07:47 lower
drwx------    2 root     root          4096 Sep  8 07:47 merged
drwx------    2 root     root          4096 Sep  8 07:47 work
/var/lib/docker/overlay2/039eb29148465722868d44cca608f800468b4fee3e17656fefe8c6849ba8a273 # 

3つのディレクトリと2つのファイルが確認できました。ここで、DockerイメージtestのGraphDriver.Data.LowerDirのハッシュ値の名前がつけられたディレクトリを見ていきます。見る時の順番はイメージのレイヤの中で低いところに位置すると考えられるものからです。mergedとworkの中身はどのディレクトリも空なので省略します。

こんな感じのシェルスクリプトを書いて

#!/bin/sh

dirs="2db33dc1bcf8c874324675de0c9a919ce9f3abbc9cfe947840fa33ea7ef38a8d
92a02a0fd5736b9fb0f2e5daa315bfd56cc753a50f38dcc34cf4c60304159016
bf8eeee84ee100f366d677e19fbea7680f87ca431f8634f14ce08bf490a013e8
3907c84a2e8cea3b5c4f8936769381a9b1c8517e1a102f1c1ca601ef84775658
9d7c5f5db93144797926396ab64b3ef9e9af755bb1ae1c374f1bc125ef8d62ee
abddae19644c1d09d312ce1dbe6c1b95815d5f9917cc0ec2fd55b7554bed6813
849ba3b8deead52bbb555dfd3003da9cc3cf1b5ed947574a945962f615b3288e
"

echo "---link---"

for dir in $dirs
do
        echo $(cat $dir/link)
done

echo -e "\n---lower---"

for dir in $dirs
do
        if [ -e $dir/lower ]; then
                echo $(cat $dir/lower)
        fi
done

echo -e "\n---diff---"

for dir in $dirs
do
        if [ -e $dir/diff ]; then
                echo $(ls $dir/diff)
        fi
done

exit 0

スクリプトを実行します

/var/lib/docker/overlay2 # ./show.sh
---link---
6CJN3N2LQUWFFE5JXD76TSGXJA
ZSG73ARDTW3UFT47AW4DJWQFAC
Z3HSFRAFYXCHT3NTSHGLPXNG5M
GIS437CEOFWNTOUFLYZ6Y5VXGV
IW4UTGZLJQFFL7YIJOORJXBOMC
DFYUB2X43MSKOPR6KPWA5NDXZS
7QZA73LSD7ZBNOEM24DB3JYCL7

---lower---
l/6CJN3N2LQUWFFE5JXD76TSGXJA
l/ZSG73ARDTW3UFT47AW4DJWQFAC:l/6CJN3N2LQUWFFE5JXD76TSGXJA
l/Z3HSFRAFYXCHT3NTSHGLPXNG5M:l/ZSG73ARDTW3UFT47AW4DJWQFAC:l/6CJN3N2LQUWFFE5JXD76TSGXJA
l/GIS437CEOFWNTOUFLYZ6Y5VXGV:l/Z3HSFRAFYXCHT3NTSHGLPXNG5M:l/ZSG73ARDTW3UFT47AW4DJWQFAC:l/6CJN3N2LQUWFFE5JXD76TSGXJA
l/IW4UTGZLJQFFL7YIJOORJXBOMC:l/GIS437CEOFWNTOUFLYZ6Y5VXGV:l/Z3HSFRAFYXCHT3NTSHGLPXNG5M:l/ZSG73ARDTW3UFT47AW4DJWQFAC:l/6CJN3N2LQUWFFE5JXD76TSGXJA
l/DFYUB2X43MSKOPR6KPWA5NDXZS:l/IW4UTGZLJQFFL7YIJOORJXBOMC:l/GIS437CEOFWNTOUFLYZ6Y5VXGV:l/Z3HSFRAFYXCHT3NTSHGLPXNG5M:l/ZSG73ARDTW3UFT47AW4DJWQFAC:l/6CJN3N2LQUWFFE5JXD76TSGXJA

---diff---
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
etc
usr
etc
etc lib tmp usr var
bin etc lib tmp usr var
usr
/var/lib/docker/overlay2 # 

なかなか面白い結果が得られたんじゃないかなと思います。

linkファイルには大文字の英字と数字からなる文字列が書かれていますが、これは自身のレイヤのdiffディレクトリを指すシンボリックリンクの名前です。

イメージの最下位のレイヤと考えられる2db33dc1bcf8…のディレクトリの下のdiffには、Debianの標準的なディレクトリ階層が存在します。これはベースイメージ(Dockerイメージの祖となるイメージ。ちなみにhttpd:2.4とcassandra:3のベースイメージはdebian:jessie)に含まれるレイヤです。これに他のディレクトリにあるdiffの内容を上乗せしていき、マージしてコンテナのディレクトリを構成するのでしょう。

lowerは上乗せしていくレイヤの順番を示しているようです。大文字の英字と数字からなる文字列はlディレクトリにあったシンボリックリンクであり、これはそれぞれdiffディレクトリのリンクとなっています。レイヤが上層になるほどlowerファイルに書かれた文字列は長くなっていきます。また、lowerファイルの文字列の一番後ろには自身のレイヤのdiffディレクトリを指すシンボリックリンクの名前を追加していっています。

まとめ

Dockerイメージはqcowやrawのように「イメージファイル」というひとまとまりにはなっておらず、分割されてレイヤとして管理されていることをこの目で確認できました。また、/var/lib/docker/images、/var/lib/docker/overlay2にどのようなファイルが置かれているのかもわかりました。今度はOverlayFSについての理解を深めるためにコンテナを起動して/var/lib/docker/overlay2ディレクトリの変化を見たいと思います。

それと、少し不思議に思ったのはdokcer pullを実行したときに「ad74af05f5a2: Pull complete 」というようなメッセージが出ますが、このハッシュ値の名前がついたファイルやディレクトリ、またこのハッシュ値が書かれたファイルがどこにも見当たらなかったことです。このハッシュ値はいったいなんなんでしょうか。

参考