When you load an image with docker load
, it doesn't have the RepoDigests
entry with the digest from the registry. There are a lot of other digests, so it's important to make sure you're comparing the same digests with each other. Specifically the image id is made from the config digest on the image, which itself uniquely defines an image since it includes the full config and layer blob digests. This isn't the same digest you'd use to pull from a registry, but does ensure the image hasn't changed:
$ regctl manifest get localhost:5000/library/alpine --platform linux/amd64
Name: localhost:5000/library/alpine
MediaType: application/vnd.docker.distribution.manifest.v2+json
Digest: sha256:a777c9c66ba177ccfea23f2a216ff6721e78a662cd17019488c417135299cd89
Total Size: 2.815MB
Config:
Digest: sha256:0ac33e5f5afa79e084075e8698a22d574816eea8d7b7d480586835657c3e1c8b
MediaType: application/vnd.docker.container.image.v1+json
Size: 1472B
Layers:
Digest: sha256:df9b9388f04ad6279a7410b85cedfdcb2208c0a003da7ab5613af71079148139
MediaType: application/vnd.docker.image.rootfs.diff.tar.gzip
Size: 2.815MB
$ regctl image export localhost:5000/library/alpine:latest@sha256:a777c9c66ba177ccfea23f2a216ff6721e78a662cd17019488c417135299cd89 ./alpine-amd64.tar
$ docker load <alpine-amd64.tar
4fc242d58285: Loading layer [==================================================>] 2.815MB/2.815MB
The image localhost:5000/library/alpine:latest already exists, renaming the old one with ID sha256:14119a10abf4669e8cdbdff324a9f9605d99697215a0d21c360fe8dfa8471bab to empty string
Loaded image: localhost:5000/library/alpine:latest
$ docker inspect localhost:5000/library/alpine:latest
[
{
"Id": "sha256:0ac33e5f5afa79e084075e8698a22d574816eea8d7b7d480586835657c3e1c8b",
"RepoTags": [
"localhost:5000/library/alpine:latest"
],
"RepoDigests": [],
...
The other option if you are planning to copy lots of images into an air gapped environment is to run your own registry, and transfer the images to that other registry using a tool like regclient, crane, or skopeo. E.g. for regclient, you can copy to and from an ocidir layout on the filesystem:
$ # export from localhost:5000
$ regctl image copy localhost:5000/library/alpine ocidir://test/alpine -v info
INFO[0000] Copy config digest="sha256:0ac33e5f5afa79e084075e8698a22d574816eea8d7b7d480586835657c3e1c8b" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy layer layer="sha256:df9b9388f04ad6279a7410b85cedfdcb2208c0a003da7ab5613af71079148139" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy config digest="sha256:cf7b6fa1108a7ad1dfcc61d4e7d7c1b62cd4550ef574df4212d7a8c7a6fada81" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy layer layer="sha256:c319b1fc4ed70b8241a7ce6ac0c4015d354bf5cf8c01eb73c50b6709c0c46e49" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy config digest="sha256:d378343b49e42a7f34e8c5a63abea857964e5ebc62628e6f9d21dda419f0efc3" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy layer layer="sha256:57fb4b5f1a47c953ca5703f0f81ce14e5d01cf23aa79558b5adb961cc526e320" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy config digest="sha256:3fb3c9af89a9178a2ab12a1f30d8df607fa46a6f176acf9448328b22d31086a2" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy layer layer="sha256:9981e73032c8833e387a8f96986e560edbed12c38119e0edb0439c9c2234eac9" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy config digest="sha256:28ca6b2fc07057618ad749d6f6403afde056ed534ba14271d6c9ead8cd1ea136" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy layer layer="sha256:73b28a5955ec7fb46f2cf0434e4901a889f7dda3f8c9ec496300feb256c7eda8" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy config digest="sha256:24d2ad2d4b14ac9edb48fb580d067884a93067ba026d6e47cd94dbc7d97b80d5" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy layer layer="sha256:1877acf2d48ed8bcb5bd9756a95aca0c077457be7cf4fcef25807f4e9be88db1" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy config digest="sha256:dc95795d85e881384cd236fbe303e7b9b31a65d2c76ec61ab55dba539f27e158" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
INFO[0000] Copy layer layer="sha256:a27b630f446c3da376a30cf610e4bfa6847f8b87c83702c29e72b986f4e52d28" source="localhost:5000/library/alpine" target="ocidir://test/alpine"
$ # import to localhost:5050, could be on another host
$ regctl image copy ocidir://test/alpine localhost:5050/import/alpine -v info
INFO[0000] Copy config digest="sha256:0ac33e5f5afa79e084075e8698a22d574816eea8d7b7d480586835657c3e1c8b" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy layer layer="sha256:df9b9388f04ad6279a7410b85cedfdcb2208c0a003da7ab5613af71079148139" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy config digest="sha256:cf7b6fa1108a7ad1dfcc61d4e7d7c1b62cd4550ef574df4212d7a8c7a6fada81" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy layer layer="sha256:c319b1fc4ed70b8241a7ce6ac0c4015d354bf5cf8c01eb73c50b6709c0c46e49" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy config digest="sha256:d378343b49e42a7f34e8c5a63abea857964e5ebc62628e6f9d21dda419f0efc3" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy layer layer="sha256:57fb4b5f1a47c953ca5703f0f81ce14e5d01cf23aa79558b5adb961cc526e320" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy config digest="sha256:3fb3c9af89a9178a2ab12a1f30d8df607fa46a6f176acf9448328b22d31086a2" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy layer layer="sha256:9981e73032c8833e387a8f96986e560edbed12c38119e0edb0439c9c2234eac9" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy config digest="sha256:28ca6b2fc07057618ad749d6f6403afde056ed534ba14271d6c9ead8cd1ea136" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy layer layer="sha256:73b28a5955ec7fb46f2cf0434e4901a889f7dda3f8c9ec496300feb256c7eda8" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy config digest="sha256:24d2ad2d4b14ac9edb48fb580d067884a93067ba026d6e47cd94dbc7d97b80d5" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy layer layer="sha256:1877acf2d48ed8bcb5bd9756a95aca0c077457be7cf4fcef25807f4e9be88db1" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy config digest="sha256:dc95795d85e881384cd236fbe303e7b9b31a65d2c76ec61ab55dba539f27e158" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
INFO[0000] Copy layer layer="sha256:a27b630f446c3da376a30cf610e4bfa6847f8b87c83702c29e72b986f4e52d28" source="ocidir://test/alpine" target="localhost:5050/import/alpine"
A simple command to run your own registry looks like:
docker run -d --restart=unless-stopped --name registry \
-e "REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry" \
-e "REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR=inmemory" \
-e "REGISTRY_STORAGE_DELETE_ENABLED=true" \
-e "REGISTRY_VALIDATION_DISABLED=true" \
-v "registry-data:/var/lib/registry" \
-p "127.0.0.1:5000:5000" \
registry:2