Skip to content

Suggestion: a "docker pull --dry-run" option #6059

Open

Description

@jmlord

Description

It would be useful in some automation environment to detect if there are new images available without pulling them right away. In my case, the launcher script detects if there is an update, and offers it to the user.

In an ideal world, I would launch docker pull --dry-run and either parse the output or check the return code.

Migrated from this issue, as suggested in the thread to make a feature request in the Docker CLI :
distribution/distribution#2412

Workaround:

It is possible to achieve this using image inspection. The following script works in my case but has major flaws : is is slow, will break if the manifest structure changes, and works only because the variant I use happens to be the first in the remote repo's manifest. I feel that there is nothing better that a docker pull to know what a docker pull should be doing, and any scripting attempt like this one is an approximation.

    images=$(docker compose config | grep 'image:' | awk '{print $2}')
    for image in $images; do
        # Get the local digest in the format sha256:<hash>
        localDigest=$(docker image inspect --format='{{index .Id}}' $image 2>/dev/null)
        if [[ $? -ne 0 ]]; then
            echo "At least one image not found locally: $image"
            updatesFound=true
            break
        fi
        echo $localDigest

        # Get the remote digest in format sha256:<hash>
        # This works ONLY if the desired config is from the first variant
        # Would have been cleaner with jq but it is not available in a git bash on Windows...
        remoteDigest=$(docker manifest inspect -v $image \
            | awk '/"config":/ {found=1} found&& /"digest"/ {print $2; exit}' \
            | tr -d '",')
        echo $remoteDigest

        # Perform comparison
        if [[ "$localDigest" == "$remoteDigest" ]]; then
            echo "Up to date: $image"
        else
            echo "At least one image outdated: $image"
            updatesFound=true
            break
        fi
    done

EDIT: Workaround does not work on a mac, as the content of docker image inspect differs.

Activity

  1. thaJeztah commented on May 13, 2025

    @thaJeztah
    Member

    This is something that has been discussed a few times (and possibly could be considered; it would require changes on the daemon-side though, which is where the actual pull is handled). That said; do you have more context on your use-case; effectively, a docker pull would not pull anything if the image is up-to-date;

    docker pull alpine
    Using default tag: latest
    latest: Pulling from library/alpine
    Digest: sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c
    Status: Image is up to date for alpine:latest
    docker.io/library/alpine:latest
    
    docker run --pull always --rm alpine echo foo
    latest: Pulling from library/alpine
    Digest: sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c
    Status: Image is up to date for alpine:latest
    foo

    I should note that with the containerd image-store integration enabled;

    The digest of the image will now reflect the digests of the "distributed" image, so should match the top-most digest from docker manifest inspect (or `docker buildx imagetools inspect)

    docker image ls --no-trunc alpine
    REPOSITORY   TAG       IMAGE ID                                                                  CREATED        SIZE
    alpine       latest    sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c   2 months ago   12.8MB
    
    docker buildx imagetools inspect alpine | head -n 3
    Name:      docker.io/library/alpine:latest
    MediaType: application/vnd.oci.image.index.v1+json
    Digest:    sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c
  2. jmlord commented on May 14, 2025

    @jmlord
    Author

    Hi Sebastiaan,

    Thanks for your reply,

    do you have more context on your use-case; effectively, a docker pull would not pull anything if the image is up-to-date;

    In our context, we have a few services running, that can be started by the users. Most users will know nothing about docker except that it is installed on their machines, the rest is handled by the launcher script.

    Why do we want to check for updates, instead of automatically pulling them?

    1. The total download is over 3GB, which can be slow for some of our users with limited bandwidth.
    2. Our containers contain dependencies (R, conda) that are installed at runtime. Installing a single R dependency can take from a few seconds to nearly an hour. While the dependencies were previously stored on volumes to avoid losing them, this caused compatibility problems when the containers updated. Hence, they are now discarded with the container. It is therefore natural to ask them permission before discarding the containers, knowing it can seriously delay their work.

    I therefore added a the above digest checking procedure to our launcher script prod-server.sh, currently in a branch here: https://github.com/GEO-BON/bon-in-a-box-pipeline-engine/tree/mamba_update_staging
    I am wary though that this can break at any moment with updates from the docker CLI tools.

  3. jmlord commented on May 28, 2025

    @jmlord
    Author

    Hi again,

    About the containerd solution, that could simplify things a lot! However, since we do not control the client environment, it would be hard to ask every user to switch to this experimental configuration. I just found out that the workaround I had pasted in the original question does not work for mac users, since the content of docker image inspect differs. We'll have to find something else...

    On the other hand I tracked the pull calls up to here (I imagine this is the Daemon-side you were referring to). I wanted to see if there was some comparing logic I could pull out, but wasn't successful.

    In conclusion, any other workaround ideas are welcome.

  4. thaJeztah commented on Jun 2, 2025

    @thaJeztah
    Member

    Docker 20.10 and newer should cache the manifest after pulling (if the containerd image store is not in use), and skip the actual pull if the content is matched; moby/moby#41607

    With the containerd image store, the same should happen (containerd always stores the manifests that it pulled);

    With a local registry (to check requests received by the registry) and the containerd image store enabled;

    docker run -d --name registry --rm -p 5002:5000 registry:2
    
    echo -e 'FROM alpine' | docker build -t host.docker.internal:5002/myimage:latest  -
    docker push host.docker.internal:5002/myimage:latest
    The push refers to repository [host.docker.internal:5002/myimage]
    6e771e15690e: Pushed
    109631c1e18d: Pushed
    latest: digest: sha256:74dbc6645ece3658846442acfeffa07d7cd0c8d0f7ca736731037a0fcce380f9 size: 855
    
    docker rmi host.docker.internal:5002/myimage:latest
    Untagged: host.docker.internal:5002/myimage:latest
    Deleted: sha256:74dbc6645ece3658846442acfeffa07d7cd0c8d0f7ca736731037a0fcce380f9
    
    docker pull host.docker.internal:5002/myimage:latest
    latest: Pulling from myimage
    Digest: sha256:74dbc6645ece3658846442acfeffa07d7cd0c8d0f7ca736731037a0fcce380f9
    Status: Downloaded newer image for host.docker.internal:5002/myimage:latest
    host.docker.internal:5002/myimage:latest
    
    docker pull host.docker.internal:5002/myimage:latest
    latest: Pulling from myimage
    Digest: sha256:74dbc6645ece3658846442acfeffa07d7cd0c8d0f7ca736731037a0fcce380f9
    Status: Image is up to date for host.docker.internal:5002/myimage:latest
    host.docker.internal:5002/myimage:latest
    
    docker pull host.docker.internal:5002/myimage:latest
    # repeat a few times

    Logs for registry container shows that the pulls only result in a HEAD request, with no GET request (as the image wasn't updated);

    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "HEAD /v2/myimage/blobs/sha256:6e771e15690e2fabf2332d3a3b744495411d6e0b00b2aea64419b58b0066cf81 HTTP/1.1" 404 157 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "HEAD /v2/myimage/blobs/sha256:baf8be4c483728b8210141e1cd2ecedc8accbbf02761527327c30a7c255e8260 HTTP/1.1" 404 157 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "HEAD /v2/myimage/blobs/sha256:8e930d459a9619d0aaa861555003823bbddffcfc467959d3b4a975a2267f38e7 HTTP/1.1" 404 157 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "HEAD /v2/myimage/blobs/sha256:109631c1e18d5b89cd07d35a818d8c68e27b43bb63b9afa8e89a73d6e3978d6c HTTP/1.1" 404 157 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "POST /v2/myimage/blobs/uploads/ HTTP/1.1" 202 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "POST /v2/myimage/blobs/uploads/ HTTP/1.1" 202 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "POST /v2/myimage/blobs/uploads/ HTTP/1.1" 202 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "POST /v2/myimage/blobs/uploads/ HTTP/1.1" 202 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "PUT /v2/myimage/blobs/uploads/a92dd6b1-1b93-4d2b-8359-84bb6418c79c?_state=dNgY57H0O55CSc_3kqiNNgII57JcyJkJniYBroHR3V57Ik5hbWUiOiJteWltYWdlIiwiVVVJRCI6ImE5MmRkNmIxLTFiOTMtNGQyYi04MzU5LTg0YmI2NDE4Yzc5YyIsIk9mZnNldCI6MCwiU3RhcnRlZEF0IjoiMjAyNS0wNi0wMlQxMzoxNzoyNi4wMzgwNzcwNDhaIn0%3D&digest=sha256%3A8e930d459a9619d0aaa861555003823bbddffcfc467959d3b4a975a2267f38e7 HTTP/1.1" 201 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "PUT /v2/myimage/blobs/uploads/cd1c34ab-542c-401b-8b79-ab6dc07c64c6?_state=Y6nCeSoAWXUZ2EOBnaxglvNx7KlytUsR39gdhTYIE6B7Ik5hbWUiOiJteWltYWdlIiwiVVVJRCI6ImNkMWMzNGFiLTU0MmMtNDAxYi04Yjc5LWFiNmRjMDdjNjRjNiIsIk9mZnNldCI6MCwiU3RhcnRlZEF0IjoiMjAyNS0wNi0wMlQxMzoxNzoyNi4wMzgyMTAwNDhaIn0%3D&digest=sha256%3A109631c1e18d5b89cd07d35a818d8c68e27b43bb63b9afa8e89a73d6e3978d6c HTTP/1.1" 201 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "PUT /v2/myimage/blobs/uploads/a2d1c5a7-b34d-4a74-b157-979c6c0f89f5?_state=45fe8dg4cuB-WVwMLnAK6tpQOIaZadfQMLWKQ2JfMmJ7Ik5hbWUiOiJteWltYWdlIiwiVVVJRCI6ImEyZDFjNWE3LWIzNGQtNGE3NC1iMTU3LTk3OWM2YzBmODlmNSIsIk9mZnNldCI6MCwiU3RhcnRlZEF0IjoiMjAyNS0wNi0wMlQxMzoxNzoyNi4wMjMzMTUxMzJaIn0%3D&digest=sha256%3Abaf8be4c483728b8210141e1cd2ecedc8accbbf02761527327c30a7c255e8260 HTTP/1.1" 201 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "PUT /v2/myimage/blobs/uploads/c2541250-ba1c-44f3-b2d0-401ce53966eb?_state=5LixxPc1v7rUPL-qgL-4rN39cMcRdm0qB2FBk3H8Ft57Ik5hbWUiOiJteWltYWdlIiwiVVVJRCI6ImMyNTQxMjUwLWJhMWMtNDRmMy1iMmQwLTQwMWNlNTM5NjZlYiIsIk9mZnNldCI6MCwiU3RhcnRlZEF0IjoiMjAyNS0wNi0wMlQxMzoxNzoyNi4wMjMzMTY5MjNaIn0%3D&digest=sha256%3A6e771e15690e2fabf2332d3a3b744495411d6e0b00b2aea64419b58b0066cf81 HTTP/1.1" 201 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "HEAD /v2/myimage/manifests/sha256:889bfea82e9b267fb1dddd2151ff87ac8a693f12dd28e088c21a57d51328c4fd HTTP/1.1" 404 183 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "HEAD /v2/myimage/manifests/sha256:ae4667b34a2eaec727d82d478001045e327c7a2d425ea8209b378cbd3a44ffa1 HTTP/1.1" 404 183 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "PUT /v2/myimage/manifests/sha256:889bfea82e9b267fb1dddd2151ff87ac8a693f12dd28e088c21a57d51328c4fd HTTP/1.1" 201 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "PUT /v2/myimage/manifests/sha256:ae4667b34a2eaec727d82d478001045e327c7a2d425ea8209b378cbd3a44ffa1 HTTP/1.1" 201 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "HEAD /v2/myimage/manifests/latest HTTP/1.1" 404 96 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:26 +0000] "PUT /v2/myimage/manifests/latest HTTP/1.1" 201 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:17:53 +0000] "HEAD /v2/myimage/manifests/latest HTTP/1.1" 200 855 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:18:08 +0000] "HEAD /v2/myimage/manifests/latest HTTP/1.1" 200 855 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:18:30 +0000] "HEAD /v2/myimage/manifests/latest HTTP/1.1" 200 855 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:20:12 +0000] "HEAD /v2/myimage/manifests/latest HTTP/1.1" 200 855 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:20:54 +0000] "HEAD /v2/myimage/manifests/latest HTTP/1.1" 200 855 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 containerd-client/2.0.5+unknown storage-driver/overlayfs UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    

    After disabling the containerd image store, and repeating the same;

    docker run -d --name registry --rm -p 5002:5000 registry:2
    echo -e 'FROM alpine' | docker build -t host.docker.internal:5002/myimage:latest  -
    docker push host.docker.internal:5002/myimage:latest
    The push refers to repository [host.docker.internal:5002/myimage]
    1231a673589a: Pushed
    latest: digest: sha256:5f24a984dc6d405d4832032310023f8033aab72ee6bd62582e446b8aafd8584f size: 527
    
    docker rmi host.docker.internal:5002/myimage:latest
    Untagged: host.docker.internal:5002/myimage:latest
    Untagged: host.docker.internal:5002/myimage@sha256:5f24a984dc6d405d4832032310023f8033aab72ee6bd62582e446b8aafd8584f
    Deleted: sha256:4b071331304977d08f6ff896f2ece366bfaa03f0c1729fa2b4331d477405140b
    
    docker pull host.docker.internal:5002/myimage:latest
    latest: Pulling from myimage
    d69d4d41cfe2: Already exists
    Digest: sha256:5f24a984dc6d405d4832032310023f8033aab72ee6bd62582e446b8aafd8584f
    Status: Downloaded newer image for host.docker.internal:5002/myimage:latest
    host.docker.internal:5002/myimage:latest
    
    docker pull host.docker.internal:5002/myimage:latest
    latest: Pulling from myimage
    Digest: sha256:5f24a984dc6d405d4832032310023f8033aab72ee6bd62582e446b8aafd8584f
    Status: Image is up to date for host.docker.internal:5002/myimage:latest
    host.docker.internal:5002/myimage:latest
    
    # repeat a few times

    Logs show that only HEAD requests are made for the manifest (the GET requests on the /v2/ endpoint are for feature discovery and don't count towards rate limits);

    192.168.65.1 - - [02/Jun/2025:13:10:47 +0000] "GET /v2/ HTTP/1.1" 200 2 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:10:47 +0000] "HEAD /v2/myimage/blobs/sha256:d69d4d41cfe2ee680d6972795e2a1eb9e4dc4ec3b3c5e0797c9ab43bb3726fa7 HTTP/1.1" 404 157 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:10:47 +0000] "POST /v2/myimage/blobs/uploads/ HTTP/1.1" 202 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:10:47 +0000] "PATCH /v2/myimage/blobs/uploads/e8083e58-d00f-4e5b-8c44-1ab280a0e75b?_state=J9j1JyYrrp2Y25E3PpjZA6MEo-jiZJ-uk9dfjrDNaAx7Ik5hbWUiOiJteWltYWdlIiwiVVVJRCI6ImU4MDgzZTU4LWQwMGYtNGU1Yi04YzQ0LTFhYjI4MGEwZTc1YiIsIk9mZnNldCI6MCwiU3RhcnRlZEF0IjoiMjAyNS0wNi0wMlQxMzoxMDo0Ny41OTM1MzYyMVoifQ%3D%3D HTTP/1.1" 202 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:10:47 +0000] "PUT /v2/myimage/blobs/uploads/e8083e58-d00f-4e5b-8c44-1ab280a0e75b?_state=o3wsRjFOBpkZkOFiIVSr7lnoOwQvpSz_zYjs97FwYCB7Ik5hbWUiOiJteWltYWdlIiwiVVVJRCI6ImU4MDgzZTU4LWQwMGYtNGU1Yi04YzQ0LTFhYjI4MGEwZTc1YiIsIk9mZnNldCI6NDEzNTk0MSwiU3RhcnRlZEF0IjoiMjAyNS0wNi0wMlQxMzoxMDo0N1oifQ%3D%3D&digest=sha256%3Ad69d4d41cfe2ee680d6972795e2a1eb9e4dc4ec3b3c5e0797c9ab43bb3726fa7 HTTP/1.1" 201 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:10:47 +0000] "HEAD /v2/myimage/blobs/sha256:d69d4d41cfe2ee680d6972795e2a1eb9e4dc4ec3b3c5e0797c9ab43bb3726fa7 HTTP/1.1" 200 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:10:48 +0000] "HEAD /v2/myimage/blobs/sha256:4b071331304977d08f6ff896f2ece366bfaa03f0c1729fa2b4331d477405140b HTTP/1.1" 404 157 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:10:48 +0000] "POST /v2/myimage/blobs/uploads/ HTTP/1.1" 202 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:10:48 +0000] "PATCH /v2/myimage/blobs/uploads/720ac455-c2b7-4e90-a28a-b724b65dd6ef?_state=vyfu2Q-RlVloVYANH3x5XAbPHKEShJ9O4H-vdVOc-6x7Ik5hbWUiOiJteWltYWdlIiwiVVVJRCI6IjcyMGFjNDU1LWMyYjctNGU5MC1hMjhhLWI3MjRiNjVkZDZlZiIsIk9mZnNldCI6MCwiU3RhcnRlZEF0IjoiMjAyNS0wNi0wMlQxMzoxMDo0OC4wMTMwMTY0MThaIn0%3D HTTP/1.1" 202 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:10:48 +0000] "PUT /v2/myimage/blobs/uploads/720ac455-c2b7-4e90-a28a-b724b65dd6ef?_state=XSfwOlpx8cJnydlFhv_uqYUYrXlUkrRJuwL9Fjk7nMd7Ik5hbWUiOiJteWltYWdlIiwiVVVJRCI6IjcyMGFjNDU1LWMyYjctNGU5MC1hMjhhLWI3MjRiNjVkZDZlZiIsIk9mZnNldCI6NTgyLCJTdGFydGVkQXQiOiIyMDI1LTA2LTAyVDEzOjEwOjQ4WiJ9&digest=sha256%3A4b071331304977d08f6ff896f2ece366bfaa03f0c1729fa2b4331d477405140b HTTP/1.1" 201 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:10:48 +0000] "HEAD /v2/myimage/blobs/sha256:4b071331304977d08f6ff896f2ece366bfaa03f0c1729fa2b4331d477405140b HTTP/1.1" 200 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:10:48 +0000] "PUT /v2/myimage/manifests/latest HTTP/1.1" 201 0 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:32 +0000] "GET /v2/ HTTP/1.1" 200 2 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:32 +0000] "HEAD /v2/myimage/manifests/latest HTTP/1.1" 200 527 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:32 +0000] "GET /v2/myimage/manifests/sha256:5f24a984dc6d405d4832032310023f8033aab72ee6bd62582e446b8aafd8584f HTTP/1.1" 200 527 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:32 +0000] "GET /v2/myimage/blobs/sha256:4b071331304977d08f6ff896f2ece366bfaa03f0c1729fa2b4331d477405140b HTTP/1.1" 200 582 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:43 +0000] "GET /v2/ HTTP/1.1" 200 2 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:43 +0000] "HEAD /v2/myimage/manifests/latest HTTP/1.1" 200 527 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:45 +0000] "GET /v2/ HTTP/1.1" 200 2 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:45 +0000] "HEAD /v2/myimage/manifests/latest HTTP/1.1" 200 527 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:47 +0000] "GET /v2/ HTTP/1.1" 200 2 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:47 +0000] "HEAD /v2/myimage/manifests/latest HTTP/1.1" 200 527 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:47 +0000] "GET /v2/ HTTP/1.1" 200 2 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
    192.168.65.1 - - [02/Jun/2025:13:11:48 +0000] "HEAD /v2/myimage/manifests/latest HTTP/1.1" 200 527 "" "docker/28.2.0-rc.2 go/go1.24.3 git-commit/32c5774 kernel/6.10.14-linuxkit os/linux arch/arm64 UpstreamClient(Docker-Client/28.2.0-rc.2 \\(darwin\\))"
  5. jmlord commented on Jun 2, 2025

    @jmlord
    Author

    Hi @thaJeztah ,

    Did you want to post this here on on this other issue: #6082 ?

    In my case, this doesn't help, since I want to detect the update without updating right away...

  6. thaJeztah commented on Jun 2, 2025

    @thaJeztah
    Member

    DOH! You're right; I think I posted it in the wrong tab! 🙈

    Let me port it in the other ticket 😅

  7. svoop commented on Sep 6, 2026

    @svoop

    Thanks for suggesting --dry-run @jmlord, this would be such a helpful feature for smaller setups in a time where zero- or subzero-day exploits are raining down permanently due to the well known changes in how attacks are being carried out nowadays. And thanks a lot for the insights @thaJeztah, obviously, it's a textbook example for a simple feature (from a user perspective) to be way more complex (from a dev perspective). Still hope it will land in some form at some point. 🙏

  8. added a commit that references this issue on Oct 13, 2026
  9. raphgm commented on Oct 13, 2026

    @raphgm

    I've opened a PR implementing this: #7379

    docker pull --dry-run <image> asks the daemon to resolve the reference to a digest in the registry (via the existing /distribution/{name}/json endpoint, so no daemon changes are needed) and compares it against the local image's RepoDigests. Nothing is downloaded. It reports one of:

    • Status: Image is up to date for <ref>
    • Status: A newer image is available for <ref>
    • Status: Image <ref> is not available locally and would be pulled

    It can't be combined with --all-tags. @thaJeztah, since you mentioned this might need daemon-side work, I'd appreciate your thoughts on whether the client-side approach is acceptable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions