めちゃくちゃ興味あり〼 https://t.co/gHfAV5rbEU
— うなすけ (@yu_suke1994) 2018年11月30日
頭の中には設計があるんですが、…
— Uchio KONDO 🔫 (@udzura) 2018年11月30日
OCIの仕様を再確認するところから…
とりあえずブログかキータ
— Uchio KONDO 🔫 (@udzura) 2018年11月30日
という訳で、書きました。
Open Container Initiativeによって定められた、コンテナイメージフォーマットの標準仕様です。
詳しくは Open Container Initiativeによるコンテナランタイムとコンテナイメージの最初の標準化作業が完了、「OCI v1.0」発表 - Publickey にて。
現在、OCI ImageをdownloadできるDocker HubのようなWebサイトは知る限りありません。なので、自分でOCI Imageを作成する必要があります。
まず、Docker Hubにて公開されているDocker imageをdownloadするところからです。以下のコマンドで、Docker Hubからダウンロードしたimageをtarballとして扱うことができるようになります。
$ docker image pull ruby:2.5.3-slim-stretch
$ docker save ruby:2.5.3-slim-stretch --output ruby_253_slim_stretch.tar
このtarを展開してみましょう。
$ tar -xf ruby_253_slim_stretch
すると、manifest.json
というファイルができているので、見てみます。
[
{
"Config":"b1c1603e80c648f3ab902b0259ab846a7779d0780124bf9e417dd4b8c3cea296.json",
"RepoTags":[
"ruby:2.5.3-slim-stretch"
],
"Layers":[
"aeff88bcdbbd12ea45c023c45f97b870492092899651c811b2ef26ae7fdf3120/layer.tar",
"c61a4dce9ddcebd63027d09811998052c9b2cdb3a379c297277cf755dfcf1420/layer.tar",
"de2944e57fc93c2f354420cb36210fd1181687a990ffd7123600fdaecba3ee83/layer.tar",
"49c3631e8651776127d66adb995e78af1e2cfc52b7a10a20df0d92d837258419/layer.tar",
"eb50b8a8210f1b43ff1571598e66b694844b2dcf6fbaa0691e8af6b7c80dcaa7/layer.tar"
]
}
]
なるほど、これはOCI image specを読むとわかるのですが、OCIに定められている形式のJSONではありませんね。
ここで、containers/skopeo というtoolを使用して、Docker imageをOCI imageに変換してみます。
$ skopeo copy docker://ruby:2.5.3-slim-stretch oci:ruby-oci:latest
すると、 ruby-oci/index.json
というファイルができているので、見てみます。
{
"schemaVersion":2,
"manifests":[
{
"mediaType":"application/vnd.oci.image.manifest.v1+json",
"digest":"sha256:a3843587af4f3e838f3e1a10649631144d4dcf4391980b64f3b902d81048057c",
"size":976,
"annotations":{
"org.opencontainers.image.ref.name":"latest"
},
"platform":{
"architecture":"amd64",
"os":"linux"
}
}
]
}
なるほど、これは OCI Image Specに定められている image manifest fileですね。
自分なりに理解しようと翻訳したもののメモになります。 正確性の保証はないです。誤訳とかあります。最後のほう力尽きてます。
high level image manifest にはcontentsとdependencies of the image including the content-addressable(連想?) identity of one of more file system layer changeset archives、展開すると最終的に実行可能なファイルシステムになる
image configuration にはapplication arguments, environmentsなどの情報
image indexには high level manifest list of manifests and discriptorsのpointが含まれる
それらのmanifestsは異なるimageの実装 ←プラットフォームや他の属性によって変化することができる
一度作成されたOCI imageは名前によって探索(discovered)、ダウンロード、hashによる検証、署名による信頼、OCI Runtime Bundleへの展開ができる
components of the specは以下を含む
optional featureとしてSignaturesやNamingが仕様に含まれるかもしれない。
application/vnd.oci.descriptor.v1+json
application/vnd.oci.layout.header.v1+json
application/vnd.oci.image.index.v1+json
application/vnd.oci.image.manifest.v1+json
application/vnd.oci.image.config.v1+json
application/vnd.oci.image.layer.v1.tar
application/vnd.oci.image.layer.v1.tar+gzip
application/vnd.oci.image.layer.nondistributable.v1.tar
application/vnd.oci.image.layer.nondistributable.v1.tar+gzip
HTTP responseのContent-Typeで上の値を返すなどのように、typeを返すなにかしらの方法を実装してもよい(MAY)、また実装はmedia typeとdigestを期待してよい? 実装は返却されたmedia typeを尊重する必要がある(SHOULD)
前方・後方互換を可能な限り維持する必要がある。
似た、または関連するmedia typeは以下
application/vnd.oci.image.index.v1+json
application/vnd.docker.distribution.manifest.list.v2+json
(mediaTypeが違う?)application/vnd.oci.image.manifest.v1+json
application/vnd.docker.distribution.manifest.v2+json
application/vnd.oci.image.layer.v1.tar+gzip
application/vnd.docker.image.rootfs.diff.tar.gzip
互換性がある(入れ替え可能)application/vnd.oci.image.config.v1+json
application/vnd.docker.container.image.v1+json
Image indexは複数のImage manifestを持つ。Image manifestとImage JSON(config)は1対1。Image manifestはLayerのtar archiveを複数持つ。 Discriptorは全ての参照を持つ。
mediaType
digest
size
urls
annotations
data
こういう形式
sha256:6c3c624b58dbbcd3c0dd82b4c53f04194d1247c6eebdaab7c610cf7d66709b3b
sha512:401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b372742...
sha256とsha512がRegistered algorithms
とされている。sha256はMUSTでsha512はMAY。
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7682,
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
"urls": ["https://example.com/example-manifest" ]
}
OCI Image LayoutはOCI content-addressable blobs と location-addressable references のための directory構造を表す(?) Layoutではtarやzipなどのarchive formats、nfsなどの共有ファイルシステム、http、ftp、rsyncなどのネットワークによるファイル取得を使用してもよい。
あるimage layoutと参照は、manifestと指定された順序で適用されるfilesystem layerとOCI runtime specificationのconfig.jsonへ変換できるimage configurationがあればOCI Runtime Specification bundleを何らかのtoolによって作成できる。(?)
blobs
directory
oci-layout
file
imageLayoutVersion
というfieldを持つ必要がある。index.json
$ cd example.com/app/
$ find . -type f
./index.json
./oci-layout
./blobs/sha256/3588d02542238316759cbf24502f4344ffcc8a60c803870022f335d1390c13b4
./blobs/sha256/4b0bc1c4050b03c95ef2a8e36e25feac42fd31283e8c30b3ee5df6b043155d3c
./blobs/sha256/7968321274dc6b6171697c33df7815310468e694ac5be0ec03ff053bb135e768
$ shasum -a 256 ./blobs/sha256/afff3924849e458c5ef237db5f89539274d5e609db5db935ed3959c90f1f2d51
afff3924849e458c5ef237db5f89539274d5e609db5db935ed3959c90f1f2d51 ./blobs/sha256/afff3924849e458c5ef237db5f89539274d5e609db5db935ed3959c90f1f2d51
blobs
のサブディレクトリ以下にあるディレクトリは、各ハッシュアルゴリズムごとにまとめられている。そのディレクトリ以下に、実際のファイルが格納されている。
blobs/<alg>/<encoded>
<alg>:<encoded>
と対応している$ cat ./blobs/sha256/9b97579de92b1c195b85bb42a11011378ee549b02d7fe9c17bf2a6b35d5cb079 | jq
{
"schemaVersion": 2,
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7143,
"digest": "sha256:afff3924849e458c5ef237db5f89539274d5e609db5db935ed3959c90f1f2d51",
"platform": {
"architecture": "ppc64le",
"os": "linux"
}
},
...
$ cat ./blobs/sha256/afff3924849e458c5ef237db5f89539274d5e609db5db935ed3959c90f1f2d51 | jq
{
"schemaVersion": 2,
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 7023,
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270"
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 32654,
"digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"
},
...
$ cat ./blobs/sha256/5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270 | jq
{
"architecture": "amd64",
"author": "Alyssa P. Hacker <alyspdev@example.com>",
"config": {
"Hostname": "8dfe43d80430",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": null,
"Image": "sha256:6986ae504bbf843512d680cc959484452034965db15f75ee8bdd1b107f61500b",
...
$ cat ./blobs/sha256/9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0
[gzipped tar stream]
これ。
{
"imageLayoutVersion": "1.0.0"
}
必須。image-layoutの参照、descriptorsのentry pointになる。/index.json
に置かれる。
"org.opencontainers.image.ref.name"
にイメージのtagが格納される?
{
"schemaVersion": 2,
"manifests": [
{
"mediaType": "application/vnd.oci.image.index.v1+json",
"size": 7143,
"digest": "sha256:0228f90e926ba6b96e4f39cf294b2586d38fbb5a1e385c05cd1ee40ea54fe7fd",
"annotations": {
"org.opencontainers.image.ref.name": "stable-release"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7143,
"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",
"platform": {
"architecture": "ppc64le",
"os": "linux"
},
"annotations": {
"org.opencontainers.image.ref.name": "v1.0"
}
},
{
"mediaType": "application/xml",
"size": 7143,
"digest": "sha256:b3d63d132d21c3ff4c35a061adf23cf43da8ae054247e32faa95494d904a007e",
"annotations": {
"org.freedesktop.specifications.metainfo.version": "1.0",
"org.freedesktop.specifications.metainfo.type": "AppStream"
}
}
],
"annotations": {
"com.example.index.revision": "r124356"
}
}
imageと、そのコンポーネントのために生成された一意なIDからハッシュ可能なimageのconfigurationimage modelをサポートした参照可能なimageを作成すること、platform固有のmanifestを含んだ"fat manifest"による複数architecture対応のimageの実現、OCI Runtime Specificationへの変換の3つを目標にしている。
image indexはarchitectureやOSごとに展開可能なそれぞれのimageの情報を持つが、image manifestは特定のarchitecture、OSに対する単一のcontainer imageにおけるconfigurationとlayerの集合を提供する。
schemaVersion
mediaType
config
layers
annotations
{
"schemaVersion": 2,
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 7023,
"digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 32654,
"digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 16724,
"digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b"
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 73109,
"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
}
],
"annotations": {
"com.example.key1": "value1",
"com.example.key2": "value2"
}
}
application/vnd.oci.image.manifest.v1+json
← これ{
"schemaVersion": 2,
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7143,
"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",
"platform": {
"architecture": "ppc64le",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7682,
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
"platform": {
"architecture": "amd64",
"os": "linux"
}
}
],
"annotations": {
"com.example.key1": "value1",
"com.example.key2": "value2"
}
}
application/vnd.oci.image.layer.v1.tar
はtar archiveでなくてはならず、またtar archiveの結果となるpathに重複したエントリを含んではいけないrootfs-c9d-v1/
etc/
my-app-config
bin/
my-app-binary
my-app-tools
色々とfilesystemについての解説が続く
application/vnd.oci.image.layer.nondistributable.v1.tar
というmediaTypeでないといけないapplication/vnd.oci.image.config.v1+json
sha256:a9561eb1b190625c9adb5a9513e72c4dedafc1cb2d4c5236c9a6957ec7dfd5a9
ChainID(L₀) = DiffID(L₀)
ChainID(L₀|...|Lₙ₋₁|Lₙ) = Digest(ChainID(L₀|...|Lₙ₋₁) + " " + DiffID(Lₙ))
VARNAME=VARVALUE
という形式で格納される。
layers
である必要がある。実装は不明な値が入っていた場合はエラーを出す必要がある。{
"created": "2015-10-31T22:22:56.015925234Z",
"author": "Alyssa P. Hacker <alyspdev@example.com>",
"architecture": "amd64",
"os": "linux",
"config": {
"User": "alice",
"ExposedPorts": {
"8080/tcp": {}
},
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"FOO=oci_is_a",
"BAR=well_written_spec"
],
"Entrypoint": [
"/bin/my-app-binary"
],
"Cmd": [
"--foreground",
"--config",
"/etc/my-app.d/default.cfg"
],
"Volumes": {
"/var/job-result-data": {},
"/var/log/my-app-logs": {}
},
"WorkingDir": "/home/alice",
"Labels": {
"com.example.project.git.url": "https://example.com/project.git",
"com.example.project.git.commit": "45a939b2999782a3f005621a8d0f29aa387e1d6b"
}
},
"rootfs": {
"diff_ids": [
"sha256:c6f988f4874bb0add23a778f753c65efe992244e148a1d2ec2a8b664fb66bbd1",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
],
"type": "layers"
},
"history": [
{
"created": "2015-10-31T22:22:54.690851953Z",
"created_by": "/bin/sh -c #(nop) ADD file:a3bc1e842b69636f9df5256c49c5374fb4eef1e281fe3f282c65fb853ee171c5 in /"
},
{
"created": "2015-10-31T22:22:55.613815829Z",
"created_by": "/bin/sh -c #(nop) CMD [\"sh\"]",
"empty_layer": true
}
]
}
com.example.myKey
みたいなorg.opencontainers
はOCIによって予約済みなので使用してはならない。org.opencontainers.image
はOCIによって予約済みなので使用してはならない。(他のOCI仕様についても同様)org.opencontainers.image.created
org.opencontainers.image.authors
org.opencontainers.image.url
org.opencontainers.image.documentation
org.opencontainers.image.source
org.opencontainers.image.version
org.opencontainers.image.revision
org.opencontainers.image.vendor
org.opencontainers.image.licenses
org.opencontainers.image.ref.name
org.opencontainers.image.title
org.opencontainers.image.description
org.opencontainers.image |
org.label-schema |
Compatibility notes |
---|---|---|
created |
build-date |
Compatible |
url |
url |
Compatible |
source |
vcs-url |
Compatible |
version |
version |
Compatible |
revision |
vcs-ref |
Compatible |
vendor |
vendor |
Compatible |
title |
name |
Compatible |
description |
description |
Compatible |
documentation |
usage |
URLの場合にはCompatible |
authors |
Label Schemaにはない要素 | |
licenses |
Label Schemaにはない要素 | |
ref.name |
Label Schemaにはない要素 | |
schema-version |
OCI Image Specにはない要素 | |
docker.* , rkt.*
|
OCI Image Specにはない要素 |
application/vnd.oci.image.config.v1+json
を OCI Runtime configuration blobに変換する方法を定義するConfig.WorkingDir
→ process.cwd
Config.Env
→ process.env
※1Config.Entrypoint
→ process.args
※2Config.Cmd
→ process.args
※2org.opencontainers.image.author
に指定する必要があるorg.opencontainers.image.created
に指定する必要があるorg.opencontainers.image.stopSignal
に指定する必要があるConfig.User
→ process.user.*
/etc/passwd
をパースすることによってprocess.user.uid や process.user.gid に値を格納するConfig.ExposedPorts
→ annotations ※1Config.Vlumes
→ mounts
※2org.opencontainers.image.exposedPorts
に値をセットしなければならない