It's a bummer right now that pullImage requires giving the fixed output derivation hash, since anything that updates an image specified in Nix source (whether manually or with automation) has to pull the entire image in order to compute that hash.
Would it be possible to implement a pull in Nix that only requires the content hashes already in the image manifest supplied by a registry? A sketch of this would be:
Individually pull each layer archive into a fixed-output-derivation, validated by the manifest-supplied hashes.
In the sandbox, combine those layers into the final image, in a new store path that can be used as a fromImage for further nix2container operations.
Not sure if the second would have to be implemented from scratch or just using the skopeo JSON manifests that nix2container already uses for building— if the layers had to be unpacked anyway, then it would be maybe possible to hardlink the files from the final derivation to avoid paying the disk cost twice. A bunch of cp -Rl actions is pretty cheap relative to assembling another JSON and calling a separate tool.
Just to put a bit more flesh on these bones— here's how to list the tags for a particular image, the latest of which at time of writing is 251a921be086aa489705e31fa5bd59f2dadfa0824aa7f362728dfe264eb6a3d2:
The manifest and blob APIs require a bearer token:
export repo=nixos/nix
export token=$(curl -sSL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repo}:pull" | jq --raw-output .token)
# Gets us the list of all the layers in the image specified by the digest
curl -H "Authorization: Bearer ${token}" "https://registry.hub.docker.com/v2/${repo}/manifests/sha256:251a921be086aa489705e31fa5bd59f2dadfa0824aa7f362728dfe264eb6a3d2"
# Pull a specific layer's archive
curl -H "Authorization: Bearer ${token}" "https://registry.hub.docker.com/v2/${repo}/blobs/sha256:7eec37a2649230139dc4534fd8b5cec45986588eee6bb30625c5b2bcf87d368c" -L --output layer.bin
We can validate that the layer matches the given content hash:
So this definitely looks doable to download and unpack the layers into the Nix store just using manifest information. My main questions then would be—
Is this something that has already been implemented somewhere and I just haven't found it?
If it hasn't been done, would there be interest in having it as part of nix2container?
If it's a new implementation, I'm assuming it would make most sense to just have Nix directly parse the manifest JSON, similar to how poetry2nix works. Then the manifest can be stored in the repo and it's trivial for users to update it with:
So there's really no need to bother about actually unpacking anything— just pull the archives and make up a similar manifest file pointing at them in their individual store paths.
It's a bummer right now that
pullImage
requires giving the fixed output derivation hash, since anything that updates an image specified in Nix source (whether manually or with automation) has to pull the entire image in order to compute that hash.Would it be possible to implement a pull in Nix that only requires the content hashes already in the image manifest supplied by a registry? A sketch of this would be:
fromImage
for further nix2container operations.Not sure if the second would have to be implemented from scratch or just using the skopeo JSON manifests that nix2container already uses for building— if the layers had to be unpacked anyway, then it would be maybe possible to hardlink the files from the final derivation to avoid paying the disk cost twice. A bunch of
cp -Rl
actions is pretty cheap relative to assembling another JSON and calling a separate tool.Just to put a bit more flesh on these bones— here's how to list the tags for a particular image, the latest of which at time of writing is
251a921be086aa489705e31fa5bd59f2dadfa0824aa7f362728dfe264eb6a3d2
:https://hub.docker.com/v2/repositories/nixos/nix/tags/latest
The manifest and blob APIs require a bearer token:
We can validate that the layer matches the given content hash:
And also verify that it's just a normal tarball of files:
So this definitely looks doable to download and unpack the layers into the Nix store just using manifest information. My main questions then would be—
If it's a new implementation, I'm assuming it would make most sense to just have Nix directly parse the manifest JSON, similar to how
poetry2nix
works. Then the manifest can be stored in the repo and it's trivial for users to update it with:Looks like the format of a
nix2container.pullImage
is really just a modified manifest pointing to the layer archives anyway, eg:So there's really no need to bother about actually unpacking anything— just pull the archives and make up a similar manifest file pointing at them in their individual store paths.