振る舞いから見る Docker プライベートレジストリ のイメージ削除について
オンプレミス上で Docker の プライベートレジストリ を運用している際に、不要な Docker イメージが蓄積されディスクスペースをひっ迫することが目に見えたので、どのように削除するのかを検証してみた。
今回は内部実装の面からではなく、ツールを利用してのイメージ削除後、レジストリ の garbage-collect コマンドを利用した際にイメージを格納しているディレクトリにどのような変化が生じるのかという面から記述していく。
記述中の詳細には深く言及しないので、別の記事で再度まとめたい。
検証環境について
自宅の Ubuntu サーバ上に以下のビルド手順を参考に実行バイナリを生成し、環境構築を実施。
Docker イメージを利用しても良かったのだけど、後々ソースコードを弄りたいと思ったときに面倒だなと思ったのでソースコードからビルドする。
distribution/BUILDING.md at master · docker/distribution · GitHub
初期のディレクトリ構造
バックエンドのストレージにローカルファイルシステムを選んだ場合、設定ファイルにイメージを格納するディレクトリを指定することができる。
指定しなければデフォルトは、/var/lib/registry
領域に格納される。
レジストリの詳しい設定は以下の公式ドキュメントに記載されている。
nginx:1.17.3 のイメージを Docker Hub から取得後、ローカルにイメージをプッシュすると以下のディレクトリとファイルが生成される。
annkara@annkara:~/registry/docker/registry$ tree -L 10 . └── v2 ├── blobs │ └── sha256 │ ├── 22 │ │ └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── data │ ├── 55 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── data │ ├── a6 │ │ └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── data │ ├── ab │ │ └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── data │ └── b8 │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── data └── repositories └── nginx ├── _layers │ └── sha256 │ ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── link │ ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── link │ ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── link │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── link ├── _manifests │ ├── revisions │ │ └── sha256 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── link │ └── tags │ └── 1.17.3 │ ├── current │ │ └── link │ └── index │ └── sha256 │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ └── link └── _uploads
v2 ディレクトリ配下に大きく二つのディレクトリが生成される。
- blobs
Docker イメージの各レイヤを構成する実データファイル(gzipで圧縮)と マニフェストと呼ばれるイメージのメタ情報が16進数のハッシュ値のディレクトリに格納される。 - repositories
リポジトリ名のディレクトリ配下に、_layers
、_manifests
、_uploads
という3つのディレクトリが作成され、イメージのタグは_manifests/tags
に現れるのがわかる。
イメージの追加
先ほどプッシュした同一のイメージID で別のタグ名を持つ nginx:1.17.13_2 をプッシュし、ディレクトリ構造にどう影響を与えるか見てみる。
annkara@annkara:~/registry/docker/registry$ tree -L 10 . └── v2 ├── blobs │ └── sha256 │ ├── 22 │ │ └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── data │ ├── 55 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── data │ ├── a6 │ │ └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── data │ ├── ab │ │ └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── data │ └── b8 │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── data └── repositories └── nginx ├── _layers │ └── sha256 │ ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── link │ ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── link │ ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── link │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── link ├── _manifests │ ├── revisions │ │ └── sha256 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── link │ └── tags │ ├── 1.17.3 │ │ ├── current │ │ │ └── link │ │ └── index │ │ └── sha256 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── link │ └── 1.17.3_2 │ ├── current │ │ └── link │ └── index │ └── sha256 │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ └── link └── _uploads
repositories/nginx/_manifests/tags
配下に 1.17.3_2 のディレクトリ・ファイルが生成されたほかは何も変化がないように見られる。
また、同一のイメージを別のタグ名でプッシュしたせいか、index 配下の sha256 のハッシュ値も 1.17.3 のタグと同一の値となっている。
nginx/1.17.3_2 のマニフェストを削除する
プライベートレジストリからイメージを削除するといった場合、2つの解釈が生じうる。
一つ目はソフト削除といって、指定されたイメージ:タグまたはダイジェストのマニフェストを削除するというもの。
この削除ではストレージ上から実際のデータを削除までは実行しないが、メタ情報が存在しないので docker image pull
コマンドでイメージを取得することができない。
二つ目はストレージから不要なイメージの実データを削除するというもの。
ストレージ上からデータを削除するには、後述する プライベートレジストリに実装されている garbage-collect
サブコマンドを実行する必要がある。
ここでは一つ目のマニフェストを削除することで、ディレクトにどのように影響を与えるか見てみる。
Docker のレジストリは Docker Registry HTTP API V2
を通じて処理をリクエストするが、curl コマンド等を利用するのは面倒なのでgenuinetools/reg
を利用して、マニフェストを削除する。
# reg を利用して 1.17.3_2 を削除 annkara@annkara:~/registry/docker/registry$ reg rm -k 192.168.1.209:5000/nginx:1.17.3_2 INFO[0000] domain: 192.168.1.209:5000 INFO[0000] server address: 192.168.1.209:5000 Deleted 192.168.1.209:5000/nginx:1.17.3_2@sha256:55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20
削除後のディレクトリは以下の通り。
annkara@annkara:~/registry/docker/registry$ tree -L 10 . └── v2 ├── blobs │ └── sha256 │ ├── 22 │ │ └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── data │ ├── 55 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── data │ ├── a6 │ │ └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── data │ ├── ab │ │ └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── data │ └── b8 │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── data └── repositories └── nginx ├── _layers │ └── sha256 │ ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── link │ ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── link │ ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── link │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── link ├── _manifests │ ├── revisions │ │ └── sha256 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ └── tags └── _uploads
tags 配下の1.17.3
と 1.17.3_2
のディレクトリの両方が削除されてしまったため、docker image pull
コマンドでイメージを取得できない。
annkara@annkara:~/registry/docker/registry$ docker image pull 192.168.1.209:5000/nginx:1.17.3 Error response from daemon: manifest for 192.168.1.209:5000/nginx:1.17.3 not found annkara@annkara:~/registry/docker/registry$ docker image pull 192.168.1.209:5000/nginx:1.17.3_2 Error response from daemon: manifest for 192.168.1.209:5000/nginx:1.17.3_2 not found
この振る舞いから、同一リポジトリ名で別のタグを指定したとしても、同一のイメージIDに基いたイメージ情報は削除されうる。
しかし、別のリポジトリ名でそれらが同一のイメージIDに基づいていた場合、指定されたイメージの情報のみが削除される。
先ほどのreg rm
コマンドは内部では以下の API リクエストを発行している。
DELETE /v2/<name>/manifests/<reference>
つまり、<reference>
の値が同一であろうと、<name>
の部分が異なれば指定されたもの以外は削除されないということ。
同一イメージID で別のリポジトリを削除した場合
上記で述べた場合を検証してみる。
192.168.1.209:5000/nginx/test:1.17.3
と 192.168.1.209:5000/nginx:1.17.3
のイメージをプッシュし、192.168.1.209:5000/nginx:1.17.3
を削除した場合にどうなるかを見てみる。
annkara@annkara:~/registry/docker/registry$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE 192.168.1.209:5000/nginx/test 1.17.3 ab56bba91343 10 days ago 126MB 192.168.1.209:5000/nginx 1.17.3 ab56bba91343 10 days ago 126MB
2つのイメージをプッシュした際のディレクトリは以下の通り、repositories 配下のディレクトリ構成が異なっている。
annkara@annkara:~/registry/docker/registry$ tree -L 11 . └── v2 ├── blobs │ └── sha256 │ ├── 22 │ │ └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── data │ ├── 55 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── data │ ├── a6 │ │ └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── data │ ├── ab │ │ └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── data │ └── b8 │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── data └── repositories └── nginx ├── _layers │ └── sha256 │ ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── link │ ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── link │ ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── link │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── link ├── _manifests │ ├── revisions │ │ └── sha256 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── link │ └── tags │ └── 1.17.3 │ ├── current │ │ └── link │ └── index │ └── sha256 │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ └── link ├── test │ ├── _layers │ │ └── sha256 │ │ ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ │ └── link │ │ ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ │ └── link │ │ ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ │ └── link │ │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ │ └── link │ ├── _manifests │ │ ├── revisions │ │ │ └── sha256 │ │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ │ └── link │ │ └── tags │ │ └── 1.17.3 │ │ ├── current │ │ │ └── link │ │ └── index │ │ └── sha256 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── link │ └── _uploads └── _uploads
ここで、reg を利用して、nginx:1.17.3 のマニフェストを削除する。
annkara@annkara:~/registry/docker/registry$ tree -L 11 . └── v2 ├── blobs │ └── sha256 │ ├── 22 │ │ └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── data │ ├── 55 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── data │ ├── a6 │ │ └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── data │ ├── ab │ │ └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── data │ └── b8 │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── data └── repositories └── nginx ├── _layers │ └── sha256 │ ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── link │ ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── link │ ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── link │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── link ├── _manifests │ ├── revisions │ │ └── sha256 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ └── tags ├── test │ ├── _layers │ │ └── sha256 │ │ ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ │ └── link │ │ ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ │ └── link │ │ ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ │ └── link │ │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ │ └── link │ ├── _manifests │ │ ├── revisions │ │ │ └── sha256 │ │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ │ └── link │ │ └── tags │ │ └── 1.17.3 │ │ ├── current │ │ │ └── link │ │ └── index │ │ └── sha256 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── link │ └── _uploads └── _uploads
改めてディレクトリ構成をみるとtest/nginx:1.17.3
のディレクトリは削除されていないため、リポジトリ名が別の場合には削除されないことがわかる。
garbage-collect の実行
今まではマニフェストの削除のみを扱ってきたが、ストレージ上からの削除を実行してみる。
ストレージ上から実データを削除するには以下のように、garbage-collect
というサブコマンドを実行する。
#!/bin/sh annkara@annkara:~/bin$ export REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/home/annkara/registry annkara@annkara:~/bin$ export REGISTRY_STORAGE_DELETE_ENABLED=True annkara@annkara:~/bin$ /home/annkara/go/bin/registry garbage-collect /home/annkara/go/src/github.com/docker/distribution/cmd/registry/config-example.yml nginx nginx/test nginx/test: marking manifest sha256:55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 nginx/test: marking blob sha256:ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 nginx/test: marking blob sha256:b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d nginx/test: marking blob sha256:a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 nginx/test: marking blob sha256:22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d 5 blobs marked, 0 blobs and 0 manifests eligible for deletion
上記の実行後のディレクトリの状態は以下の通り。
annkara@annkara:~/registry/docker/registry$ tree -L 11 . └── v2 ├── blobs │ └── sha256 │ ├── 22 │ │ └── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── data │ ├── 55 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── data │ ├── a6 │ │ └── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── data │ ├── ab │ │ └── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── data │ └── b8 │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── data └── repositories └── nginx ├── _layers │ └── sha256 │ ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── link │ ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── link │ ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── link │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── link ├── _manifests │ ├── revisions │ │ └── sha256 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ └── tags ├── test │ ├── _layers │ │ └── sha256 │ │ ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ │ └── link │ │ ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ │ └── link │ │ ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ │ └── link │ │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ │ └── link │ ├── _manifests │ │ ├── revisions │ │ │ └── sha256 │ │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ │ └── link │ │ └── tags │ │ └── 1.17.3 │ │ ├── current │ │ │ └── link │ │ └── index │ │ └── sha256 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── link │ └── _uploads └── _uploads
test/nginx:1.17.3
が存在するため、実データは削除されずまだ存在している。
次に、test/nginx:1.17.3
を削除し、gabage-collect を実行する。
annkara@annkara:~/bin$ /home/annkara/go/bin/registry garbage-collect /home/annkara/go/src/github.com/docker/distribution/cmd/registry/config-example.yml nginx nginx/test 0 blobs marked, 5 blobs and 0 manifests eligible for deletion blob eligible for deletion: sha256:22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/22/22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d go.version=go1.13 instance.id=c488cc07-8cee-4cdc-bbfe-3a6a3df72af5 service=registry blob eligible for deletion: sha256:55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/55/55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 go.version=go1.13 instance.id=c488cc07-8cee-4cdc-bbfe-3a6a3df72af5 service=registry blob eligible for deletion: sha256:a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/a6/a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 go.version=go1.13 instance.id=c488cc07-8cee-4cdc-bbfe-3a6a3df72af5 service=registry blob eligible for deletion: sha256:ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/ab/ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 go.version=go1.13 instance.id=c488cc07-8cee-4cdc-bbfe-3a6a3df72af5 service=registry blob eligible for deletion: sha256:b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d INFO[0000] Deleting blob: /docker/registry/v2/blobs/sha256/b8/b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d go.version=go1.13 instance.id=c488cc07-8cee-4cdc-bbfe-3a6a3df72af5 service=registry
実行後のディレクトリの状態。
blobs
配下のディレクトリは残っているものの、実データが削除されていることがわかる。
annkara@annkara:~/registry/docker/registry$ tree -L 11 . └── v2 ├── blobs │ └── sha256 │ ├── 22 │ ├── 55 │ ├── a6 │ ├── ab │ └── b8 └── repositories └── nginx ├── _layers │ └── sha256 │ ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ └── link │ ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ └── link │ ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ └── link │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ └── link ├── _manifests │ ├── revisions │ │ └── sha256 │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ └── tags ├── test │ ├── _layers │ │ └── sha256 │ │ ├── 22a7aa8442bf42f645c988589059966cb4bc9ca05b712cea56ae26dcd7477a6d │ │ │ └── link │ │ ├── a6639d774c21523ed49d1becdfc9af3e6f7bc1814c2ac5c74f1c96d48a311053 │ │ │ └── link │ │ ├── ab56bba91343aafcdd94b7a44b42e12f32719b9a2b8579e93017c1280f48e8f3 │ │ │ └── link │ │ └── b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d │ │ └── link │ ├── _manifests │ │ ├── revisions │ │ │ └── sha256 │ │ │ └── 55e7a6f2bb43e38cc34285af03b4973d61f523d26cd8a57e9d00cf4154792d20 │ │ └── tags │ └── _uploads └── _uploads