Blog Post

Hocker, I can’t believe it’s not docker!

Introduction

hocker is a suite of utilities that:

  • fetch the registry manifest for a docker image
  • fetch the configuration of a docker image
  • fetch any layer of a docker image
  • fetch and assemble a whole docker image
  • generate Nix build instructions from a registry manifest for a docker image (we won’t cover this utility in this post)

hocker utilities support two modes of authentication with privately hosted docker registries and “transparent” public-token authentication for the public docker hub registry.

hocker does not replace docker; however, it does decouple fetching docker images from running docker containers.

Why did you build this?

There are two motivating reasons:

  • we want to assemble a docker image from our registry without requiring the docker daemon
  • we want to fetch individual layers of a docker image from our registry for a granular — and efficient — deployment of a docker image to environments where we cannot use docker pull

Integrating docker containers into a NixOS system (without using docker pull) stimulated these two requirements. Note that Nix and NixOS are not required to use these utilities.

Fetch a docker image without using docker pull

Let’s dive right in and fetch the hello-world docker image from hub.docker.com (note that the repository name for official images on the public docker hub is “library”):

$ hocker-image 
--out ./hello-world.tar.gz 
library/hello-world linux
Downloading layer: ca4f61b => decompressed => wrote f999ae2
./hello-world.tar.gz

The result is a complete docker image:

$ tar --list --file ./hello-world.tar.gz
manifest.json
f2a91732366c0332ccd7afd2a5c4ff2b9af81f549370f7a19acd460f87686bc7.json
f999ae22f308fea973e5a25b57699b5daf6b0f1150ac2a5c2ea9d7fecee50fdf.tar
repositories

… which we load into docker using docker load:

$ docker load < hello-world.tar.gz
...
Loaded image: registry-1.docker.io/v2/library/hello-world:linux

… and then run:

$ docker run --rm 
registry-1.docker.io/v2/library/hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
...

Fetch the registry manifest and a layer, of a docker image

If we want to fetch the individual layers of a docker image then we need to retrieve the manifest of binary blobs on the registry for the image; we can do this using hocker-manifest:

$ hocker-manifest library/hello-world linux | jq
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 1510,
"digest": "sha256:f2a91732366c0332ccd7afd2a5c4ff2b9af81f549370f7a19acd460f87686bc7"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 985,
"digest": "sha256:ca4f61b1923c10e9eb81228bd46bee1dfba02b9c7dac1844527a734752688ede"
}
]
}

… the manifest says there is one layer we can fetch; the layer is keyed by its digest with the sha256: part stripped off:

$ hocker-layer 
--out ./hello-world-layer-ca4f61b.tar.gz 
--layer ca4f61b1923c10e9eb81228bd46bee1dfba02b9c7dac1844527a734752688ede 
library/hello-world linux
Downloading layer: ca4f61b => wrote ca4f61b
./hello-world-layer-ca4f61b.tar.gz

… the layer contains a hello program:

$ tar --list --file ./hello-world-layer-ca4f61b.tar.gz
hello

… which is also the CMD entrypoint of the container as indicated by the image’s configuration JSON:

$ hocker-config library/hello-world linux | jq
{
...
"config": {
...
"Cmd": [
"/hello"
],
...
},
...
}

Conclusion

We’ve pulled a docker image from a registry without using the docker client or going through the docker daemon. We also fetched three other artifacts of the hello-world docker image that the stock docker tooling elides from you:

    • the registry’s manifest of the artifacts that compose the image
    • an individual layer of the image; and,
    • the image configuration — as JSON

In a follow-on blogpost, I will show how we use the hocker utilities with Nix and NixOS.

You can find hocker on GitHub and Hackage.

Notes

Thanks to Gabriel Gonzalez (@GabrielG439) for reading drafts and providing feedback.

Subscribe!

If you liked what you just read, subscribe to hear about our threat research and security analysis.

Parnell Springmeyer
Parnell Springmeyer

Member of Technical Staff