Add some of my hacking notes which have helped me figure out these APIs relationships
This commit is contained in:
parent
665bd286a6
commit
fe173e0e6c
|
@ -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 <<manifest-list>> 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 <<manifest>> 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 <<manifest>> 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"
|
||||
]
|
||||
}
|
||||
}
|
||||
----
|
Loading…
Reference in New Issue