A registry stores images and serves them over HTTP. docker push uploads an image's layers and manifest to it, and docker pull downloads them.
this host registry
┌────────────────────────────┐ push ┌─────────────────────────┐
│ localhost:5000/status-page │ ───────► │ status-page │
│ :1.0.0 (f7c0d1be242a) │ ◄─────── │ 1.0.0 → sha256:6b4c… │
└────────────────────────────┘ pull └─────────────────────────┘Run a registry
The registry:2 image is the reference registry server. It listens on port 5000 and stores images in a volume at /var/lib/registry.
docker run -d -p 5000:5000 --name registry registry:2Docker allows plain HTTP to registries on 127.0.0.0/8, so localhost:5000 works without TLS.
Tag, then push
The registry address must be part of the image name:
docker tag status-page:1.0.0 localhost:5000/status-page:1.0.0
docker push localhost:5000/status-page:1.0.0The push refers to repository [localhost:5000/status-page]
ef4dd89b49f9: Pushed
262eb80f463e: Pushed
5a77b1eca73f: Pushed
...
1.0.0: digest: sha256:6b4c4afb1f830937811e6b244d931d02449cbba4aca40c6a5492536093fc7dac size: 1665Each line is one layer. The last line is the tag and the manifest digest the registry stored. Layers the registry already has print Layer already exists and are not uploaded again.
Common push errors
| Error | Cause |
|---|---|
denied: requested access to the resource is denied | The name has no registry, so the push went to Docker Hub |
dial tcp 127.0.0.1:5000: connect: connection refused | No registry is listening on that port |
no basic auth credentials | The registry needs docker login first |
An image does not exist locally with the tag | You have not tagged the image with that name |
See what the registry holds
The registry has an HTTP API under /v2/:
curl -s localhost:5000/v2/_catalog
curl -s localhost:5000/v2/status-page/tags/list{"repositories":["status-page"]}
{"name":"status-page","tags":["1.0.0"]}Private registries need a login
Company registries require credentials before a push:
docker login registry.pier.internalUsername: deployer
Password:
WARNING! Your password will be stored unencrypted in /home/learner/.docker/config.json.
...
Login SucceededIn scripts, pass the password on standard input so it does not appear in the process list or shell history:
echo "$REGISTRY_PASSWORD" | docker login registry.pier.internal -u deployer --password-stdinCredentials are stored per registry host. Then tag and push as before:
docker tag status-page:1.0.0 registry.pier.internal/pier/status-page:1.0.0
docker push registry.pier.internal/pier/status-page:1.0.0The same image gets the same digest in both registries. docker logout registry.pier.internal removes the stored credentials.