Contents

Docker Push Tutorial: Push Images to a Registry (--all-tags, docker login)

docker push uploads an image to a registry. You usually set the target name with docker tag first. For Docker Hub, see Docker Hub.

Syntax

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
docker push [OPTIONS] NAME[:TAG]
docker login [OPTIONS] [SERVER]

Options

OptionDescription
-a, --all-tagsPush all tags of an image
--platform STRINGPush the manifest for the specified platform as a single-platform image; this does not push the image index, so other manifests, including attestations, are not preserved. Format: os[/arch[/variant]], for example, linux/amd64
-q, --quietSuppress verbose output
-p, --password STRINGPassword or Personal Access Token (PAT); use - to read from stdin
--password-stdinRead the password or Personal Access Token (PAT) from stdin
-u, --username STRINGUsername

If you don't specify a server for docker login, Docker Hub is used by default. The target name format for docker tag is TARGET_IMAGE[:TAG].

Example

The following example uses the local Registry at localhost:5000 and tags alpine:3.23 in the tools/alpine repository.

Create target tags

$ docker tag alpine:3.23 localhost:5000/tools/alpine:3.23

$ docker tag alpine:3.23 localhost:5000/tools/alpine:latest

$ docker images localhost:5000/tools/alpine
IMAGE                                ID             DISK USAGE   CONTENT SIZE   EXTRA
localhost:5000/tools/alpine:3.23     ff7f0c727dd7       26.6MB         8.21MB        
localhost:5000/tools/alpine:latest   ff7f0c727dd7       26.6MB         8.21MB        
  • Both tags point to the same image ID.
  • Each target name includes the registry host and port, repository, and tag.

Push one tag and all tags

$ docker push localhost:5000/tools/alpine:3.23
The push refers to repository [localhost:5000/tools/alpine]
5e9b4a97f639: Unavailable
5e9b4a97f639: Pushed
3.23: digest: sha256:3d67941fed5ae436b2bb9791cb3f50a252441c7706bbc5b4e738936df8ff8306 size: 1022

 Info -> Not all multiplatform-content is present and only the available single-platform image was pushed
         sha256:ff7f0c727dd796aa36787bfcd9a64bf35a6ce72a73451b3359fde849b6703d63 -> sha256:3d67941fed5ae436b2bb9791cb3f50a252441c7706bbc5b4e738936df8ff8306

$ docker push localhost:5000/tools/alpine:latest
The push refers to repository [localhost:5000/tools/alpine]
5e9b4a97f639: Layer already exists
latest: digest: sha256:3d67941fed5ae436b2bb9791cb3f50a252441c7706bbc5b4e738936df8ff8306 size: 1022

 Info -> Not all multiplatform-content is present and only the available single-platform image was pushed
         sha256:ff7f0c727dd796aa36787bfcd9a64bf35a6ce72a73451b3359fde849b6703d63 -> sha256:3d67941fed5ae436b2bb9791cb3f50a252441c7706bbc5b4e738936df8ff8306

$ docker push --all-tags localhost:5000/tools/alpine
The push refers to repository [localhost:5000/tools/alpine]
5e9b4a97f639: Layer already exists
3.23: digest: sha256:3d67941fed5ae436b2bb9791cb3f50a252441c7706bbc5b4e738936df8ff8306 size: 1022
5e9b4a97f639: Layer already exists
latest: digest: sha256:3d67941fed5ae436b2bb9791cb3f50a252441c7706bbc5b4e738936df8ff8306 size: 1022

 Info -> Not all multiplatform-content is present and only the available single-platform image was pushed
         sha256:ff7f0c727dd796aa36787bfcd9a64bf35a6ce72a73451b3359fde849b6703d63 -> sha256:3d67941fed5ae436b2bb9791cb3f50a252441c7706bbc5b4e738936df8ff8306

 Info -> Not all multiplatform-content is present and only the available single-platform image was pushed
         sha256:ff7f0c727dd796aa36787bfcd9a64bf35a6ce72a73451b3359fde849b6703d63 -> sha256:3d67941fed5ae436b2bb9791cb3f50a252441c7706bbc5b4e738936df8ff8306
  • A single-tag push reports a digest. If you push the same layer again, the output shows Layer already exists.
  • --all-tags pushes both 3.23 and latest in tools/alpine at once.
  • Info message: alpine:3.23 is a multi-platform image, but only some platform content is available locally, so only the currently available single-platform image was pushed (the digest changed from ff7f0c… to the single-platform 3d6794…). The push succeeded; the tag in the registry simply has one platform. To push a multi-platform image, see Multi-platform images.

Check registry tags and identify errors

$ wget -qO- http://localhost:5000/v2/tools/alpine/tags/list
{"name":"tools/alpine","tags":["3.23","latest"]}

$ docker push localhost:5000/tools/missing:1.0
The push refers to repository [localhost:5000/tools/missing]
tag does not exist: localhost:5000/tools/missing:1.0

$ docker push docker.io/library/alpine:3.23
The push refers to repository [docker.io/library/alpine]
5e9b4a97f639: Unavailable
5e9b4a97f639: Unavailable
5e9b4a97f639: Unavailable
5e9b4a97f639: Unavailable
5e9b4a97f639: Unavailable
5e9b4a97f639: Unavailable
5e9b4a97f639: Unavailable
5e9b4a97f639: Unavailable
5e9b4a97f639: Unavailable
5e9b4a97f639: Layer already exists
failed commit on ref "manifest-sha256:3d67941fed5ae436b2bb9791cb3f50a252441c7706bbc5b4e738936df8ff8306": server message: insufficient_scope: authorization failed
  • The registry tag list confirms that both 3.23 and latest exist. Pushing a local tag that doesn't exist returns tag does not exist.
  • When pushing docker.io/library/alpine to Docker Hub, the final error is insufficient_scope: authorization failed: library/ is the namespace for official images, and no one can push to it.
  • To push to Docker Hub, first run docker login (see the options in the table above), then tag the image under your account, for example, your-account/alpine:3.23.

Exercises

Exercise: Tag the local alpine:3.23 as localhost:5000/tools/alpine:latest, then push all tags in tools/alpine.

Answer
docker tag alpine:3.23 localhost:5000/tools/alpine:latest
docker push --all-tags localhost:5000/tools/alpine

FAQ

Why add a registry tag before pushing an image?

docker tag creates a target name that points to the source image. The example tags alpine:3.23 as localhost:5000/tools/alpine:3.23, then pushes that name.

Which tags does docker push --all-tags push?

It pushes all tags in the specified repository. In the example, both 3.23 and latest in tools/alpine are pushed.

What should I do if pushing to Docker Hub returns insufficient_scope?

It means you don't have permission to push to this repository. In the example, docker.io/library/alpine is the namespace for official Docker images, where personal accounts cannot push. To push to Docker Hub, run docker login first, then tag the image as your-account/name:tag and push it. See [Push to Docker Hub](/docker/docker-hub/).

Is the single-platform Info message after a successful push an error?

The example reports the tag's digest, then says that only the available single-platform image was pushed. This is an Info message; it does not mean the push failed.

Updated October 26, 2026