We Need to Talk About Docker Registries
Many Docker tutorials begin with docker pull
as the first command to cover. The docker pull
command is followed by the "tag" of a Docker image that we want to be pulled. Say that we wanted the latest Alpine Linux image (I picked this due to its minimal size):
docker pull alpine:latest
# latest: Pulling from library/alpine
# 530afca65e2e: Pull complete
# Digest: sha256:7580ece7963bfa...
# Status: Downloaded newer image for alpine:latest
# docker.io/library/alpine:latest
But where does this image come from?
What is a Docker registry?
Where does the Docker command line interface (CLI for short) pulls the images from? The answer is on the last line of the output. docker.io
is the URL for a so called Docker registry. In this case, it refers to the default registry, Docker Hub, applied when you don't specify a registry URL as part of the pull command.
Docker Hub is a service provided by Docker for finding and sharing container images.
The registry URL is usually followed by the user or organization ID, the repository name, the image name and the tag: <registry>/<user>/<repository>/<image>:<tag>
.
In short, a Docker registry stores Docker images. This is where we push images to and pull images from:
Read more about how the different parts of the Docker system relate to each other in this introductory post:
Why do you need a registry?
You might think that you only need a registry because you need to pull your parent images (like Ubuntu, Alpine, r-base
from the Rocker project etc.) from somewhere. Then you can build your Docker images locally using a Dockerfile, and run them. Why bother with a registry at all?
You can even use the docker save
and docker load
commands to save to a compressed tar file:
docker pull alpine:latest
docker save -o alpine-latest.tar alpine:latest
ls -sh alpine-latest.tar
# 11368 alpine-latest.tar
Then take this tar file, copy it to another server and load it:
docker load --input alpine-latest.tar
now imagine that you are managing more than two servers, or you want to share the Docker image with others (to use it or to serve as a parent image). The save/copy/load workflow becomes cumbersome.
In this case, using a registry might be a much better idea. Luckily, there are many options to choose from, and you can even host your own registry.
Roll your own registry
If you want a registry hosted on your machine, just pull the registry image. The next command will pull the registry
image, and run the similarly named container in the background on port 5000:
docker run -d \
-p 5000:5000 \
--restart=always \
--name registry registry:2
Tag the Alpine image with the URL of your local registry, localhost:5000
, and push the image:
docker tag alpine:latest localhost:5000/my-alpine
docker push localhost:5000/my-alpine
Remove the images so the docker images
will not list these anymore:
docker image remove alpine:latest
docker image remove localhost:5000/my-alpine
Pull the image from the local registry and list it with docker images
to verify that it is there again:
docker pull localhost:5000/my-alpine
Stop and remove the registry container. The -v
option makes sure to remove anonymous volumes associated with the container which is often used to mount a volume from your hard drive into the container where the images are stored:
docker container stop registry && \
docker container rm -v registry
If you want your own registry to be accessed over a network, then you need to think about security and access control.
Setting up transport layer security (TLS) for HTTPS and user authentication are all advanced topics, so implement those at your own risk.
For now, we will continue with a hosted registry, as most people do.
Log into a registry
When you work with private registries or private images, you need to log in with the docker login
command. For Docker Hub, just type docker login
. For all other registries, type in the registry URL as well, e.g. docker login ghcr.io
.
The Docker CLI then will prompt you for your username and password (or access token).
You can log in programmatically by providing your username and the password through standard input:
export CR_PAT=YOUR_TOKEN
echo $CR_PAT | docker login ghcr.io -u USER --password-stdin
As an alternative, the password can be provided via a file, this approach won't leave trace of your token in your history:
cat ~/my_password.txt | docker login -u USER --password-stdin
Use one of these approaches to log into any public or private repository for which you have credentials. The credentials will be stored locally: in $HOME/.docker/config.json
on Linux or %USERPROFILE%/.docker/config.json
on Windows. After login, there is no need to re-authenticate until you log out with docker logout
.
Note that docker login
requires users to use sudo
or be root
in most cases.
It is always a good idea to use a token instead of your password. Tokens can have limited scope (i.e. only for pulling images), and can be revoked at any time without it impacting other areas of your life.
Commonly used registries
There are many registries out there besides Docker Hub. Here is a non-exhaustive list of options.
GitHub container registry (the ghcr.io
URL from above) is available as part of GitHub Packages for free and paid plans, even for private repositories under the free plan. This registry requires authentication using your GitHub token.
An alternative to GitHub is GitLab (registry.gitlab.com
), which has provided registry support for its free (public and private) repositories long before GitHub. The docs are also much better in my opinion, and the whole experience is tightly integrated with GitLab's CICD pipelines. This registry also needs login with a token.
Heroku comes with a Docker registry (registry.heroku.com
) where the Docker-based deploys push the images to.
Of course, every major cloud provider offers a Docker container registry that is often integrated with their other offerings. Latency should be minimal due to network proximity to the servers:
- Amazon Elastic Container Registry (Amazon ECR)
- Azure Container Registry
- Google Container Registry
- DigitalOcean Container Registry
Other common alternatives for container registries, Helm charts, etc., include:
Although these services are called "container registry", but strictly speaking they store container images.
Summary
We reviewed what container registries are, how to access them, and what are the commonly used services out there that you can leverage for your workflow.
You have now a good understanding of where the images go after push and where the images come from after pull.