docker / cli

The Docker CLI
Apache License 2.0
4.97k stars 1.94k forks source link

Support multiple targets for docker image tag command #5605

Open jarqvi opened 2 weeks ago

jarqvi commented 2 weeks ago

- What I did

- How I did it

- How to verify it

- Description for the changelog

- A picture of a cute animal (not mandatory but encouraged)

thaJeztah commented 2 weeks ago

Thanks for contributing! I think this change may need a bit of discussion before we move ahead.

The current approach is the equivalent to running docker image tag multiple times; while this "works" and does make the UX a bit easier, there are some issues we may run into in that case, and perhaps it'd be good to address those before we add a friendlier UX only;

  1. The current tag API uses named references as input (image:tag); the daemon looks up the image, and if found, tags it with the new name:tag
  2. This means that tagging image:tag multiple times may result in the operation not being atomic; image:tag may be removed at any point, in which case "some" tags were created (but not all)
  3. There's also a risk of race-conditions in other ways; image:tag may be updated between those calls, and because the daemon-side resolves the image's ID for each tag call, means that some of the tags may be pointing to a different digest than others.

I think ideally this would be resolved on the daemon side, and instead of accepting a single ?tag=xxx query-arg, we would accept multiple; in that case, the daemon can perform the lookup, and tag the image with multiple tags.

However, we could do an alternative; the good news is tagging also works using the digest of the image;

docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
Digest: sha256:d211f485f2dd1dee407a80973c8f129f00d54604d2c90732e8e320e5038a0348
Status: Image is up to date for hello-world:latest
docker.io/library/hello-world:latest

docker image tag hello-world@sha256:d211f485f2dd1dee407a80973c8f129f00d54604d2c90732e8e320e5038a0348 my-image:latest

docker image ls

REPOSITORY                             TAG          IMAGE ID       CREATED         SIZE
hello-world                            latest       d211f485f2dd   18 months ago   21kB
my-image                               latest       d211f485f2dd   18 months ago   21kB

The alternative here would be for the CLI to resolve the image's digest, then to tag each image using that digest. The image's digest can't change, and if the original image is removed beteen calls, the digest wouldn't be removed (unless all tags referring to it would be removed), so the sequence would be;

  1. If a single tag is passed, go as usual, and tag the image (tag <image name or digest> <new tag>)
  2. if multiple tags are passed, then;
    • resolve the "source" image if it's not a digest (image:tag -> image@sha256.....)
    • look through each tag to tag it, using the image@sha256... as "source image", (tag image@sha256.. new-image:tag1, tag image@sha256.. new-image:tag2, ...)

However it looks like there's some limitations here;

Tagging the image using its (short) ID fails without the containerd image-store enabled (I'm suspecting the second case may actually be a bug, as it's attempting to use sha256: as name of the image);

docker image tag d211f485f2dd my-image:latest
Error response from daemon: No such image: d211f485f2dd:latest

docker image tag d211f485f2dd1dee407a80973c8f129f00d54604d2c90732e8e320e5038a0348 my-image:latest
Error response from daemon: No such image: sha256:d211f485f2dd1dee407a80973c8f129f00d54604d2c90732e8e320e5038a0348

So maybe the correct solution would be to move the "multiple tags" to the daemon side :thinking: This is a bit related to the discussion on this ticket;

jarqvi commented 1 week ago

So maybe the correct solution would be to move the "multiple tags" to the daemon side 🤔

Thank you for reviewing. I will create a new PR soon to support multiple targets for tagging the image in the daemon. Please keep this PR open so I can make any necessary changes in the future.