OCI image-specについて
概要
OCI image-specを実際のnginxイメージから少し理解を深めてみる.
作業
nginxイメージをOCIイメージとしてダウンロード
skopeoを使う.
OCI Image ImplementatinsにOCI specを満たすツール一覧があり, skopeoはその一番目にあると言う理由だけで採用した.
skopeoを使ってnginxイメージをダウンロードすると以下レイアウトになる.
skopeo copy docker://nginx:latest oci:nginx-image:latest
tree nginx-image
nginx-image
├── blobs
│ └── sha256
│ ├── 1fbb850f12af0a4d2bb020ef8aa7b14eb84b9fb67ba1ba731150e9aefc93ba04
│ ├── 31a65c800bdcb184f4c7386a7ef724b085b953a8c36edfe6284649a08652b8c6
│ ├── 3a1b8f20135650110763d223f82a25007e00b28b268e6a875fe87c85ba7570e4
│ ├── 3f9582a2cbe7197f39185419c0ced2c986389f8fc6aa805e1f5c090eea6511e0
│ ├── 6058e3569a68e825f1085592ab0bb04c29345726119ed059ad933c0d9af5f533
│ ├── 73ae4d4511202a823260a789f97afb3a46b8c9172ae8d99d22a5a16ad2fa673b
│ ├── 9a8c6f28671867118799d40ec6748ffbd9eab3747503ca47a2a79856dffc7553
│ └── e81b85700bc2530b1298885f74210138872f60cd139920b54aef3d268d61f0de
├── index.json
└── oci-layout
2 directories, 10 files
ファイルの確認
oci-layout
oci-layoutではimageLayoutVersionが書かれている.
jq . oci-layout 1 ↵
{
"imageLayoutVersion": "1.0.0"
}
index.json
詳細はimage-index.mdに記載されている.
そのためそれぞれの項目の説明をしないが重要なのはmanifestsのdigest. sha256:
に続くハッシュ値が後述のblob/sha256
以下にあるマニフェストファイル名となる. この例だとblob/sha256/1fbb850f12af0a4d2bb020ef8aa7b14eb84b9fb67ba1ba731150e9aefc93ba04
がマニフェストファイルである.
jq . index.json
{
"schemaVersion": 2,
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:1fbb850f12af0a4d2bb020ef8aa7b14eb84b9fb67ba1ba731150e9aefc93ba04",
"size": 1126,
"annotations": {
"org.opencontainers.image.ref.name": "latest"
}
}
]
}
blobs/sha256
このフォルダ以下のファイル群が一番重要.
manifest
まずはマニフェストファイルを覗いてみる. 詳細はmanifest.msに記載されている. これを見るとおおまかにconfigとlayersで構成されていることがわかる. このmanifestファイルからどのハッシュ値がイメージを構成するレイヤなのか辿ることができる.
jq . blobs/sha256/1fbb850f12af0a4d2bb020ef8aa7b14eb84b9fb67ba1ba731150e9aefc93ba04
{
"schemaVersion": 2,
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"digest": "sha256:31a65c800bdcb184f4c7386a7ef724b085b953a8c36edfe6284649a08652b8c6",
"size": 6565
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:3f9582a2cbe7197f39185419c0ced2c986389f8fc6aa805e1f5c090eea6511e0",
"size": 31411403
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:9a8c6f28671867118799d40ec6748ffbd9eab3747503ca47a2a79856dffc7553",
"size": 25471180
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:e81b85700bc2530b1298885f74210138872f60cd139920b54aef3d268d61f0de",
"size": 626
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:73ae4d4511202a823260a789f97afb3a46b8c9172ae8d99d22a5a16ad2fa673b",
"size": 956
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:6058e3569a68e825f1085592ab0bb04c29345726119ed059ad933c0d9af5f533",
"size": 772
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:3a1b8f20135650110763d223f82a25007e00b28b268e6a875fe87c85ba7570e4",
"size": 1402
}
]
}
config
詳細はconfig.mdに記載されている. このファイルから直接コンテナを作るわけではないが, イメージの情報が格納されており, コンテナランタイムやコマンドラインツールに利用される模様. 今回の例では上記のmanifestファイルからblobs/sha256/31a65c800bdcb184f4c7386a7ef724b085b953a8c36edfe6284649a08652b8c6
がconfigファイルにあたる. 中身が長いのでここでは表示しない.
layer
layerがimageの実体になる. manifestファイルから以下のハッシュ値がイメージを構成するファイル群となる. これの詳細もlayer.mdに記載されている
3f9582a2cbe7197f39185419c0ced2c986389f8fc6aa805e1f5c090eea6511e0
9a8c6f28671867118799d40ec6748ffbd9eab3747503ca47a2a79856dffc7553
e81b85700bc2530b1298885f74210138872f60cd139920b54aef3d268d61f0de
73ae4d4511202a823260a789f97afb3a46b8c9172ae8d99d22a5a16ad2fa673b
6058e3569a68e825f1085592ab0bb04c29345726119ed059ad933c0d9af5f533
3a1b8f20135650110763d223f82a25007e00b28b268e6a875fe87c85ba7570e4
レイヤ用のディレクトリlayer[1-6]を作り, それぞれのディレクトリにlayerファイルを展開して確認してみる.
tar -C layer1 -xf blobs/sha256/3f9582a2cbe7197f39185419c0ced2c986389f8fc6aa805e1f5c090eea6511e0
ls layer1
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
tar -C layer2 -xf blobs/sha256/9a8c6f28671867118799d40ec6748ffbd9eab3747503ca47a2a79856dffc7553
ls layer2
docker-entrypoint.d etc lib tmp usr var
tar -C layer3 -xf blobs/sha256/e81b85700bc2530b1298885f74210138872f60cd139920b54aef3d268d61f0de ls layer3
docker-entrypoint.sh
tar -C layer4 -xf blobs/sha256/73ae4d4511202a823260a789f97afb3a46b8c9172ae8d99d22a5a16ad2fa673b
tree layer4
layer4
└── docker-entrypoint.d
└── 10-listen-on-ipv6-by-default.sh
tar -C layer5 -xf blobs/sha256/6058e3569a68e825f1085592ab0bb04c29345726119ed059ad933c0d9af5f533
tree layer5
layer5
└── docker-entrypoint.d
└── 20-envsubst-on-templates.sh
tar -C layer6 -xf blobs/sha256/3a1b8f20135650110763d223f82a25007e00b28b268e6a875fe87c85ba7570e4
tree layer6
layer6
└── docker-entrypoint.d
└── 30-tune-worker-processes.sh
まとめるには例えばrootfs
以下で以下コマンドを実行する. このrootfs
以下のディレクトリ構成がコンテナで利用するファイルシステムとなる.
for layer in `cat layers.txt`; do tar -C rootfs -xf blobs/sha256/$layer; done
ls rootfs
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
umociを使えばこのようにシェルコマンドでファイルシステムを展開する必要はないが, 確認のため今回はシェルコマンドで試してみた.
mediaTypeについて
今まで説明しなかったがそれぞれのdigestにmediaTypeというのが紐づいている. digestはただのハッシュ値なのでこれを見るだけでは何なのかわからないが, mediaTypeを確認することによってそのハッシュ値が何を表しているのかわかる.
今回の例のlayerの場合, application/vnd.oci.image.layer.v1.tar+gzip
となっているが, これはアーカイブされたファイル/フォルダ群をgzip圧縮していることがわかる.
mediaTypeの種類はmedia-types.mdで定義されている.
所感
触り程度にはOCI image-specの理解ができたと思う.
Discussion