1

I want to transfer the docker image to another machine that does not have access to registry. So I'm trying to use docker save/load:

➜  ~ docker save k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.0@sha256:f3b6b39a6062328c095337b4cadcefd1612348fdd5190b1dcbcb9b9e90bd8068 -o test.tar
➜  ~ docker load -i test.tar
Loaded image ID: sha256:17e55ec30….

The digests don't match. Why and can I make them the same?

deevroman
  • 99
  • 1
  • 2
  • 14

1 Answers1

2

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
BMitch
  • 231,797
  • 42
  • 475
  • 450