From fe173e0e6c455cfe647ab91daf65371398aae96f Mon Sep 17 00:00:00 2001 From: "R. Tyler Croy" Date: Sun, 20 Oct 2019 11:29:36 -0700 Subject: [PATCH] Add some of my hacking notes which have helped me figure out these APIs relationships --- HACKING.adoc | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 HACKING.adoc diff --git a/HACKING.adoc b/HACKING.adoc new file mode 100644 index 0000000..9007740 --- /dev/null +++ b/HACKING.adoc @@ -0,0 +1,225 @@ += Hacking Ahab + +This document contains a loose collection of notes on how to hack Ahab. + + +== Example Responses + +=== Manifests API + +[[manifest-list]] +==== Manifest List + +This is an example manifest list which was pulled from the registry for +`library/alpine:latest`. Since the image is a multi-platform image, the +manifest list was returned. + +In order to fetch the manifests for a single architecture, the same manifests +API endpoint would then be hit, except the last argument of the URL would be +the specific architecture's manifest digest rather than a tag or reference. + +[source, json] +---- +{ + "manifests": [ + { + "digest": "sha256:acd3ca9941a85e8ed16515bfc5328e4e2f8c128caa72959a58a127b7801ee01f", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "platform": { + "architecture": "amd64", + "os": "linux" + }, + "size": 528 + }, + { + "digest": "sha256:0489474da8ea22426ece86ace6c1c0026ab2fd3cdfbbd62b7e94650266c37d9a", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "platform": { + "architecture": "arm", + "os": "linux", + "variant": "v6" + }, + "size": 528 + }, + { + "digest": "sha256:1316a4e4b2361242457f4136cc409c38e8a48ffda76e4e1be31896006e5fc4a2", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "platform": { + "architecture": "arm", + "os": "linux", + "variant": "v7" + }, + "size": 528 + }, + { + "digest": "sha256:db7f3dcef3d586f7dd123f107c93d7911515a5991c4b9e51fa2a43e46335a43e", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "platform": { + "architecture": "arm64", + "os": "linux", + "variant": "v8" + }, + "size": 528 + }, + { + "digest": "sha256:499416c8a5bcb311d75e12fb4667886e32b43aaf11003be2a334cbe265e81ce4", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "platform": { + "architecture": "386", + "os": "linux" + }, + "size": 528 + }, + { + "digest": "sha256:5abbfe2915ad8c466bf6c9f33d03622cde0298c36cd88f55d16a3aa3d9c2c35e", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "platform": { + "architecture": "ppc64le", + "os": "linux" + }, + "size": 528 + }, + { + "digest": "sha256:43955d6857268cc948ae9b370b221091057de83c4962da0826f9a2bdc9bd6b44", + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "platform": { + "architecture": "s390x", + "os": "linux" + }, + "size": 528 + } + ], + "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", + "schemaVersion": 2 +} +---- + + +[[manifest]] +==== Manifest + +The link:https://docs.docker.com/registry/spec/manifest-v2-2/[Manifest v2, +schema 2] is returned when the manifests API is hit with a manifest digest, or +if the image has only one architecture. + +The example below is the `amd64` manifest from the <> above. + +[source,json] +---- +{ + "schemaVersion": 2, + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "config": { + "mediaType": "application/vnd.docker.container.image.v1+json", + "size": 1512, + "digest": "sha256:961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4" + }, + "layers": [ + { + "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", + "size": 2789669, + "digest": "sha256:9d48c3bd43c520dc2784e868a780e976b207cbf493eaff8c6596eb871cbd9609" + } + ] +} +---- + +=== Image Configuration + +The image configuration is just a blob which can be fetched from the +link:https://docs.docker.com/registry/spec/api/#pulling-a-layer[blob API]. This +is a critical part of the pulling of an image and is responsible for describing +what the image should actually do to the daemon. + +There is a tight coupling between the <> and the image configuration, +since the manifest must refer to the computed "digest" (e.g. sha256 checksum) +of the image configuration. There is also a coupling between the layers listed +in the <> and the image configuration which contains the `rootfs` +property. This property has a `diff_ids` sub-property which is an array of all +the layers. Except those layers are not referred to by a digest of the +`layer.tar.gz`, instead the values of `diff_ids` must be digests of the +`layer.tar` (note: not gzipped). + +This is explained a bit further in link:https://medium.com/@saschagrunert/demystifying-containers-part-iii-container-images-244865de6fef[this blog post]. + + +The example below is from the `hello-world` image. + +[source,json] +---- +{ + "architecture": "amd64", + "config": { + "Hostname": "", + "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": [ + "/hello" + ], + "ArgsEscaped": true, + "Image": "sha256:a6d1aaad8ca65655449a26146699fe9d61240071f6992975be7e720f1cd42440", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": null + }, + "container": "8e2caa5a514bb6d8b4f2a2553e9067498d261a0fd83a96aeaaf303943dff6ff9", + "container_config": { + "Hostname": "8e2caa5a514b", + "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": [ + "/bin/sh", + "-c", + "#(nop) ", + "CMD [\"/hello\"]" + ], + "ArgsEscaped": true, + "Image": "sha256:a6d1aaad8ca65655449a26146699fe9d61240071f6992975be7e720f1cd42440", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": {} + }, + "created": "2019-01-01T01:29:27.650294696Z", + "docker_version": "18.06.1-ce", + "history": [ + { + "created": "2019-01-01T01:29:27.416803627Z", + "created_by": "/bin/sh -c #(nop) COPY file:f77490f70ce51da25bd21bfc30cb5e1a24b2b65eb37d4af0c327ddc24f0986a6 in / " + }, + { + "created": "2019-01-01T01:29:27.650294696Z", + "created_by": "/bin/sh -c #(nop) CMD [\"/hello\"]", + "empty_layer": true + } + ], + "os": "linux", + "rootfs": { + "type": "layers", + "diff_ids": [ + "sha256:af0b15c8625bb1938f1d7b17081031f649fd14e6b233688eea3c5483994a66a3" + ] + } +} +----