何の話かというと
Dockerイメージは複数のレイヤーが重なった形になっています。このあたりを内部構造とあわせて解説します。前提の環境は、CentOS7です。(つまり、ローカルのイメージ管理は、dm-thinが前提。)
# rpm -q docker docker-0.11.1-22.el7.centos.x86_64
ローカルにイメージをpullする時の動作
まず、ローカルのイメージをすべて消してキレイな体にしておきます。
# systemctl stop docker.service # rm -rf /var/lib/docker/* # systemctl start docker.service
CentOSの公式イメージをpullします。この時、4つのイメージ(b1bd49907d55、b157b77b1a65、511136ea3c5a、34e94e67e63a)がダウンロードされます。
# docker pull centos Pulling repository centos b1bd49907d55: Download complete b157b77b1a65: Download complete 511136ea3c5a: Download complete 34e94e67e63a: Download complete
しかしながら、imagesで確認しても、2種類のイメージ(b1bd49907d55、b157b77b1a65)しか見えません。
# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE centos centos6 b1bd49907d55 2 days ago 212.5 MB centos centos7 b157b77b1a65 2 days ago 243.7 MB centos latest b157b77b1a65 2 days ago 243.7 MB
これは、上記のイメージを作成する時に、ベースイメージがあって、それに修正を加える形で作成したためです。-vオプションで、イメージの親子関係が分かります。
# docker images -v Warning: '-v' is deprecated, it will be removed soon. See usage. digraph docker { base -> "511136ea3c5a" [style=invis] "511136ea3c5a" -> "34e94e67e63a" "34e94e67e63a" -> "b1bd49907d55" "b1bd49907d55" [label="b1bd49907d55\ncentos:centos6",shape=box,fillcolor="paleturquoise",style="filled,rounded"]; "34e94e67e63a" -> "b157b77b1a65" "b157b77b1a65" [label="b157b77b1a65\ncentos:centos7\ncentos:latest",shape=box,fillcolor="paleturquoise",style="filled,rounded"]; base [style=invisible] }
ツリーにするとこんな感じ。
base | 511136ea3c5a | 34e94e67e63a | |------------------------------------- | | b1bd49907d55 b157b77b1a65 ↑ ↑ centos:centos6 centos:centos7, centos:latest
これは、4種類のイメージを順番にダウンロードして、ローカルのdm-thinの論理デバイスに格納する順番に対応しています。
最初に「base」という空っぽのイメージからスナップショットを作って、その中に「511136ea3c5a」に対するtarを展開します。これが、「511136ea3c5a」の実体です。
次に、「511136ea3c5a」からスナップショットを作って、その中に「34e94e67e63a」に対応するtarを展開します。この時、「34e94e67e63a」に対応するtarの中身は、「34e94e67e63a」全体ではなくて、「34e94e67e63a」と「511136ea3c5a」の差分のみが入っています。
同様に、「34e94e67e63a」からスナップショットを作って、その中に「b1bd49907d55」に対応するtarを展開します。この時、「b1bd49907d55」に対応するtarの中身は、「b1bd49907d55」全体ではなくて、「b1bd49907d55」と「34e94e67e63a」の差分のみが入っています。
それぞれのイメージの「差分tar」の実体は、savaコマンドでイメージを書き出すと分かります。
# docker save centos:centos6 > centos6.tar # tar -tvf centos6.tar drwx------ 0/0 0 2014-08-02 14:29 ./ drwxr-xr-x 0/0 0 2014-08-02 14:29 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/ -rw-r--r-- 0/0 3 2014-08-02 14:29 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/VERSION -rw-r--r-- 0/0 1565 2014-08-02 14:29 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/json -rw-r--r-- 0/0 1024 2014-08-02 14:29 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/layer.tar drwxr-xr-x 0/0 0 2014-08-02 14:29 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/ -rw-r--r-- 0/0 3 2014-08-02 14:29 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/VERSION -rw-r--r-- 0/0 585 2014-08-02 14:29 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/json -rw-r--r-- 0/0 1536 2014-08-02 14:29 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tar drwxr-xr-x 0/0 0 2014-08-02 14:29 centos:centos6/ -rw-r--r-- 0/0 3 2014-08-02 14:29 centos:centos6/VERSION -rw-r--r-- 0/0 1574 2014-08-02 14:29 centos:centos6/json -rw-r--r-- 0/0 222638592 2014-08-02 14:29 centos:centos6/layer.tar
書きだされたtarファイルの中には、さらに3つのlayer.tarというtarファイルがあります。これらが、それぞれ、上位イメージとの差分を含むtarファイルになります。
ただし、各tarファイルのサイズから分かるように、この場合は、最後のlayer.tarにファイルの実体がほとんど詰まっているようです。おそらく、最初の2つは、Dockerfileでイメージを作った時に、MAINTAINERなどのメタデータだけを設定してcommitしたものだと思われます。
これではちょっと詰まらないので、centos:centos6をベースにさらに新しいイメージを作ってみます。
# docker run -it --name hoge centos:centos6 /bin/bash bash-4.1# echo hoge > /root/hoge.txt bash-4.1# exit exit # docker commit hoge hoge:latest aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2 # docker rm hoge hoge
できたイメージをsaveで取り出します。
# docker save hoge > hoge.tar # tar -tvf hoge.tar # tar -tvf hoge.tar drwx------ 0/0 0 2014-08-02 14:49 ./ drwxr-xr-x 0/0 0 2014-08-02 14:49 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/ -rw-r--r-- 0/0 3 2014-08-02 14:49 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/VERSION -rw-r--r-- 0/0 1565 2014-08-02 14:49 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/json -rw-r--r-- 0/0 1024 2014-08-02 14:49 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/layer.tar drwxr-xr-x 0/0 0 2014-08-02 14:49 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/ -rw-r--r-- 0/0 3 2014-08-02 14:49 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/VERSION -rw-r--r-- 0/0 585 2014-08-02 14:49 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/json -rw-r--r-- 0/0 1536 2014-08-02 14:49 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tar drwxr-xr-x 0/0 0 2014-08-02 14:49 aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/ -rw-r--r-- 0/0 3 2014-08-02 14:49 aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/VERSION -rw-r--r-- 0/0 1285 2014-08-02 14:49 aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/json -rw-r--r-- 0/0 3584 2014-08-02 14:49 aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/layer.tar drwxr-xr-x 0/0 0 2014-08-02 14:49 b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef/ -rw-r--r-- 0/0 3 2014-08-02 14:49 b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef/VERSION -rw-r--r-- 0/0 1574 2014-08-02 14:49 b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef/json -rw-r--r-- 0/0 222638592 2014-08-02 14:49 b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef/layer.tar -rw-r--r-- 0/0 86 2014-08-02 14:49 repositories # tar -xvf hoge.tar aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/layer.tar aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/layer.tar # tar -tvf aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/layer.tar -rw------- 0/0 32 2014-08-02 14:34 .bash_history dr-xr-x--- 0/0 0 2014-08-02 14:34 root/ -rw-r--r-- 0/0 5 2014-08-02 14:34 root/hoge.txt
この例から分かるように、最後のレイヤーの中身は、追加したファイル「/root/hoge.txt」のみが含まれています。
ここまでをまとめると、次のようになります。
・Dockerのイメージは、イメージを作った時の手順に従ったレイヤー構造になっている。
・DockerHubからイメージをpullすると、各レイヤーの差分のtarファイルが個別にダウンロードされた後、dm-thinによるスナップショットと連携しながら、各イメージの実体を復元していく。
・saveコマンドで、再度、各レイヤーの差分をtarファイルとして取り出すことができる。
なお、dm-thinの仕組み上は、一旦、下位のディスクイメージが復元できれば、上位のイメージは削除することも可能です。(スナップショットは論理的には独立したデバイスとして扱えるので。)しかしながら、上位のイメージを削除すると、saveコマンドで差分を再現することができなくなります。そのため、イメージを復元した後も依存関係のある上位イメージは、内部的には削除せずに残されます。(というか、もともとAUFSでやってた時は、AUFSの仕組み上、消せなかったという事情もあると思いますが。)
「-a」オプションをつけると、内部的に保存されているイメージも表示することができます。
# docker images -a REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE hoge latest aff9664bf7d8 21 minutes ago 212.5 MB centos centos6 b1bd49907d55 2 days ago 212.5 MB centos centos7 b157b77b1a65 2 days ago 243.7 MB centos latest b157b77b1a65 2 days ago 243.7 MB <none> <none> 34e94e67e63a 8 weeks ago 0 B <none> <none> 511136ea3c5a 13 months ago 0 B
また、「docker history」でイメージの親をたどることもできます。下記の例では、Dockerfileでビルドした時の中間イメージが親のイメージになっていることが分かります。
# docker history centos:centos6 IMAGE CREATED CREATED BY SIZE b1bd49907d55 30 hours ago /bin/sh -c #(nop) ADD file:5e220e99326e53ed32 212.5 MB 34e94e67e63a 8 weeks ago /bin/sh -c #(nop) MAINTAINER The CentOS Proje 0 B 511136ea3c5a 13 months ago 0 B
DockerHubの内部構造
それでは、これらのイメージを保存するDockerHubの内部は、どのような構造になっているのでしょうか? DockerHubの中身を見ることはできないので、ローカルにプライベートレジストリーを構築して確認してみます。ここでは、ローカルの「/var/lib/docker-registry」にイメージが保存されるようにしています。
# mkdir /var/lib/docker-registry # docker run -itd -p 5000:5000 -v /var/lib/docker-registry:/tmp/registry --name myregistry registry
プライベートレジストリーにpushするときは、はじめに、「ホスト名:ポート番号/リポジトリー:タグ名」というちょっと特殊なリポジトリー名をつける必要があります。
# docker tag hoge:latest localhost:5000/hoge:latest # docker images | grep hoge hoge latest aff9664bf7d8 28 minutes ago 212.5 MB localhost:5000/hoge latest aff9664bf7d8 28 minutes ago 212.5 MB
イメージIDを見ると分かるように、これは、同じイメージに対して、2種類のリポジトリー名を付与しているだけです。実体は同じです。
それでは、ローカルのプライベートレジストリーにpushします。
# docker push localhost:5000/hoge:latest The push refers to a repository [localhost:5000/hoge] (len: 1) Sending image list Pushing repository localhost:5000/hoge (1 tags) 511136ea3c5a: Image successfully pushed 34e94e67e63a: Image successfully pushed b1bd49907d55: Image successfully pushed aff9664bf7d8: Image successfully pushed Pushing tag for rev [aff9664bf7d8] on {http://localhost:5000/v1/repositories/hoge/tags/latest}
依存関係のある親のイメージがまとめてpushされていることが分かります。先ほどのsaveと同じ方法で、各レイヤーの差分tarを作成して、差分tarをレジストリー内に保存しています。
ほんまかいな、と思う方のために、イメージを保存したディレクトリーの中を直接に覗いてみます。
# ls -lR /var/lib/docker-registry/images/ /var/lib/docker-registry/images/: 合計 0 drwxr-xr-x 2 root root 60 8月 2 15:02 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a drwxr-xr-x 2 root root 60 8月 2 15:02 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158 drwxr-xr-x 2 root root 60 8月 2 15:02 aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2 drwxr-xr-x 2 root root 60 8月 2 15:02 b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef /var/lib/docker-registry/images/34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a: 合計 16 -rw-r--r-- 1 root root 75 8月 2 15:02 _checksum -rw-r--r-- 1 root root 136 8月 2 15:02 ancestry -rw-r--r-- 1 root root 1541 8月 2 15:02 json -rw-r--r-- 1 root root 23 8月 2 15:02 layer /var/lib/docker-registry/images/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158: 合計 16 -rw-r--r-- 1 root root 75 8月 2 15:02 _checksum -rw-r--r-- 1 root root 68 8月 2 15:02 ancestry -rw-r--r-- 1 root root 483 8月 2 15:02 json -rw-r--r-- 1 root root 86 8月 2 15:02 layer /var/lib/docker-registry/images/aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2: 合計 16 -rw-r--r-- 1 root root 75 8月 2 15:02 _checksum -rw-r--r-- 1 root root 272 8月 2 15:02 ancestry -rw-r--r-- 1 root root 1285 8月 2 15:02 json -rw-r--r-- 1 root root 225 8月 2 15:02 layer /var/lib/docker-registry/images/b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef: 合計 74280 -rw-r--r-- 1 root root 75 8月 2 15:02 _checksum -rw-r--r-- 1 root root 204 8月 2 15:02 ancestry -rw-r--r-- 1 root root 1550 8月 2 15:02 json -rw-r--r-- 1 root root 76048722 8月 2 15:02 layer # file /var/lib/docker-registry/images/aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/layer /var/lib/docker-registry/images/aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/layer: gzip compressed data # tar -tvzf /var/lib/docker-registry/images/aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/layer -rw------- 0/0 32 2014-08-02 14:34 .bash_history dr-xr-x--- 0/0 0 2014-08-02 14:34 root/ -rw-r--r-- 0/0 5 2014-08-02 14:34 root/hoge.txt
まさに、先ほどsaveコマンドで取り出したのと同じ構造がディレクトリー内にできていることが分かります。
この時、/imagesディレクトリーの下は、イメージIDのみで管理されており、それぞれのイメージがどのリポジトリーに属するかなどの情報は無いことに注意してください。リポジトリーというのは、イメージに対する単なるラベル(リンク)であって、イメージの実体には直接関係していません。リポジトリーの情報は、別途、下記のディレクトリーに保存されています。
# ls -lR /var/lib/docker-registry/repositories /var/lib/docker-registry/repositories: 合計 0 drwxr-xr-x 3 root root 17 8月 2 15:02 library /var/lib/docker-registry/repositories/library: 合計 0 drwxr-xr-x 2 root root 75 8月 2 15:02 hoge /var/lib/docker-registry/repositories/library/hoge: 合計 16 -rw-r--r-- 1 root root 304 8月 2 15:02 _index_images -rw-r--r-- 1 root root 160 8月 2 15:02 json -rw-r--r-- 1 root root 64 8月 2 15:02 tag_latest -rw-r--r-- 1 root root 160 8月 2 15:02 taglatest_json
それではここで、イメージ「hoge:latest」の親となるイメージ「centos:centos6」をレジストリーにpushするとどうなるか分かるでしょうか? 実は、これに対応するイメージ本体「b1bd49907d55」はすでにレジストリーにpushされているので、再度、イメージが転送されることはありません。
# docker tag centos:centos6 localhost:5000/centos:centos6 # docker push localhost:5000/centos:centos6 The push refers to a repository [localhost:5000/centos] (len: 1) Sending image list Pushing repository localhost:5000/centos (1 tags) Image 511136ea3c5a already pushed, skipping Image 34e94e67e63a already pushed, skipping Image b1bd49907d55 already pushed, skipping Pushing tag for rev [b1bd49907d55] on {http://localhost:5000/v1/repositories/centos/tags/centos6}
上記の出力から分かるように、保存済みのイメージに対して、リポジトリー(タグ)の情報だけを追加しています。
つまり、Dockerのレジストリー(DockerHub)というのは、下図のような、すべての差分tarの巨大な保管庫が1つある形になります。それとは別に、ユーザー個別のリポジトリーの管理情報があって、各イメージに対するリンク情報が保存されているというわけです。
これを見ると、仮に、centosというリポジトリーのオーナーと、hogeというリポジトリーのオーナーが違っていても、実際のイメージのデータ(差分tar)は共有する形で保存されていることが分かります。世界中の多数のユーザーが、それぞれ個別にイメージをアップロードすると、DockerHubのディスクなんてすぐに一杯になる気がしますが、このように、世界中のすべてのユーザーで差分tarを共有することにより、ディスクの使用量を抑えているというわけですね。
ちなみに、DockerHubでは、「プライベートリポジトリー」を作成することもできますが、これも、プライベートなのは、右側のリポジトリーのメタ情報だけであって、その実体の差分tarは、他のユーザーと共有する形で、同じ保管庫に入っているようです。
レイヤーの統合方法
さて、こうなると、レイヤーを統合して、1つのイメージにしてからレジストリーにpushしたいと考える人もいるかも知れません。1つの方法は、イメージのexport/importです。
起動中のコンテナーに対して、「docker export」を実行すると、ルートファイルシステム以下を単純にtarにまとめたファイルが生成されます。これを元に、「docker import」で、再度、イメージを作成すると、親のイメージを持たない、シングルレイヤーのイメージになります。ただし、各種メタデータはなくなるので、そのあたりは、再度、追加が必要です。
# docker run -itd --name hoge hoge:latest /bin/bash faee1d99e81038333f142f2f8fef78c5ff286e96e093fcd6704a3004164959f3 # docker export hoge > hoge_single.tar # docker stop hoge # docker rm hoge # tar -tvf hoge_single.tar | head dr-xr-xr-x 0/0 0 2014-08-02 15:32 ./ -rw------- 0/0 32 2014-08-02 14:34 .bash_history -rwxr-xr-x 0/0 0 2014-08-02 15:32 .dockerenv -rwxr-xr-x 0/0 0 2014-08-02 15:32 .dockerinit dr-xr-xr-x 0/0 0 2014-07-26 12:45 bin/ -rwxr-xr-x 0/0 24232 2014-06-25 17:55 bin/arch lrwxrwxrwx 0/0 0 2014-07-26 12:44 bin/awk -> gawk -rwxr-xr-x 0/0 23720 2014-06-25 17:55 bin/basename -rwxr-xr-x 0/0 903336 2013-07-18 22:19 bin/bash -rwxr-xr-x 0/0 45224 2014-06-25 17:55 bin/cat # cat hoge_single.tar | docker import - hoge:single 1bfcd9eeb52cc7168df943c78a1297120eb99c72363a44b218b2aaaf4828eb7a # docker images -v hoge:single Warning: '-v' is deprecated, it will be removed soon. See usage. digraph docker { base -> "1bfcd9eeb52c" [style=invis] "1bfcd9eeb52c" [label="1bfcd9eeb52c\nhoge:single",shape=box,fillcolor="paleturquoise",style="filled,rounded"]; base [style=invisible] }
レジストリー保存イメージの削除
それでは、レジストリーに保存したリポジトリーを削除すると、レジストリー内部では何がおきるのでしょうか。REST APIを使って、リポジトリーの削除を行ってみます。
# curl -XDELETE http://localhost:5000/v1/repositories/hoge/ true # curl -XDELETE http://localhost:5000/v1/repositories/centos/ true # ls -lR /var/lib/docker-registry/images/ /var/lib/docker-registry/images/: 合計 0 drwxr-xr-x 2 root root 60 8月 2 15:02 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a drwxr-xr-x 2 root root 60 8月 2 15:02 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158 drwxr-xr-x 2 root root 60 8月 2 15:02 aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2 drwxr-xr-x 2 root root 60 8月 2 15:02 b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef /var/lib/docker-registry/images/34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a: 合計 16 -rw-r--r-- 1 root root 75 8月 2 15:02 _checksum -rw-r--r-- 1 root root 136 8月 2 15:02 ancestry -rw-r--r-- 1 root root 1541 8月 2 15:02 json -rw-r--r-- 1 root root 23 8月 2 15:02 layer /var/lib/docker-registry/images/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158: 合計 16 -rw-r--r-- 1 root root 75 8月 2 15:02 _checksum -rw-r--r-- 1 root root 68 8月 2 15:02 ancestry -rw-r--r-- 1 root root 483 8月 2 15:02 json -rw-r--r-- 1 root root 86 8月 2 15:02 layer /var/lib/docker-registry/images/aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2: 合計 16 -rw-r--r-- 1 root root 75 8月 2 15:02 _checksum -rw-r--r-- 1 root root 272 8月 2 15:02 ancestry -rw-r--r-- 1 root root 1285 8月 2 15:02 json -rw-r--r-- 1 root root 225 8月 2 15:02 layer /var/lib/docker-registry/images/b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef: 合計 74280 -rw-r--r-- 1 root root 75 8月 2 15:02 _checksum -rw-r--r-- 1 root root 204 8月 2 15:02 ancestry -rw-r--r-- 1 root root 1550 8月 2 15:02 json -rw-r--r-- 1 root root 76048722 8月 2 15:02 layer
はい。イメージの実体(差分tar)はしっかり残っています。リポジトリーからのリンク情報を削除しているだけのようです。
それぞれのイメージ(差分tar)には、UUID(世界で唯一の固有のID)としてのイメージIDが振られているので、再度、同じイメージをpushした際は、保存済みイメージが再利用されますので、「ゴミ」というわけではありません。一度、作成して、レジストリーにpushしたイメージは、世界に固有の存在として永遠に残るという考え方のようですね。。。。
なお、これはレジストリー内部の話であって、ローカルにダウンロードしたイメージの場合は、子供のイメージを削除して、依存関係の無くなった親イメージは自動的に削除されるようになっています。