Docker : Using a Local Docker Registry
This article demonstrates how to use a local Docker registry based on the Docker "registry" image.
- Why do you need a local registry?
- Start a Local Registry
- Use the Local Registry
- Persistent Storage
- HTTPS Enable the Local Registry
Why do you need a local registry?
Public registries can be updated at any time. There is nothing to stop an image update having the same tag as a previous image. As such, if you rely on a public registry, there are no guarantees that each environment is really based on the same base images.
If you are using images directly from public registries, you should pull them down to your system, and upload them to you own registry, so you have some control over the release of updates.
Start a Local Registry
Pull a version of the "registry" image from the Docker Hub.
docker pull registry:2.7.1
Start a container based on the "registry" image. Notice port 5000 is used externally, and internally.
docker run -d \ --name registry \ --restart always \ -p 5000:5000 \ registry:2.7.1
We can see the container running using the
docker ps command.
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 00e2cdc36a8e registry:2.7.1 "/entrypoint.sh /etc…" 8 minutes ago Up 8 minutes 0.0.0.0:5000->5000/tcp registry $
The registry container is managed just like any other container.
Use the Local Registry
Now we need to start pushing images to the registry. We pull the "oraclelinux:8-slim" image from a public registry, like Docker Hub, tag it and push it to the local registry. Notice the tag includes the HTTP path to the registry, including the port.
docker pull oraclelinux:8-slim docker tag oraclelinux:8-slim localhost:5000/oraclelinux:8-slim docker push localhost:5000/oraclelinux:8-slim
With the image now in the registry, we can remove the locally cached versions of the images, so any subsequent references are based on the image in the local registry.
docker image remove oraclelinux:8-slim docker image remove localhost:5000/oraclelinux:8-slim
From this point, new containers based on the "oraclelinux:8-slim" image should be pulled from the local registry.
docker pull localhost:5000/oraclelinux:8-slim docker run -d \ --name ol8 \ --restart always \ localhost:5000/oraclelinux:8-slim
We can see we are using the images from the local repository when we use the
docker ps command.
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ea08963e8eaa localhost:5000/oraclelinux:8-slim "/bin/bash" 4 seconds ago Restarting (0) 1 second ago ol8 00e2cdc36a8e registry:2.7.1 "/entrypoint.sh /etc…" 14 minutes ago Up 14 minutes 0.0.0.0:5000->5000/tcp registry $
The images in the registry are important, so you should use persistent storage. You can do this using the "-v" option, mounting your persistent storage to the "/var/lib/registry" location in the registry container. If we were using a host volume based on the "/u01/volumes/registry" directory on the host machine, we might start the registry container as follows.
#docker rm -vf registry docker run -d \ --name registry \ --restart always \ -v /u01/volumes/registry:/var/lib/registry \ -p 5000:5000 \ registry:2.7.1
HTTPS Enable the Local Registry
In the previous examples we were only accessing the registry from the local server. That's not practical, so we need to make it available to other servers, which means we need to make it available over HTTPS. It would be good if we had a real certificate, but here we'll just use a self-signed certificate as an example.
Create a location for the certificates on the host server.
mkdir -p /u01/registry_certs
Create a self-signed certificate.
openssl req \ -newkey rsa:4096 -nodes -sha256 -keyout /u01/registry_certs/registry.localdomain.key \ -x509 -days 3650 -out /u01/registry_certs/registry.localdomain.crt \ -subj "/CN=Tim Hall/O=Example Company/L=Birmingham/ST=West Midlands/C=GB"
Recreate the docker container. Notice the
REGISTRY_HTTP_* environment variables, specifying the listening address of "0.0.0.0:443" and the location of the certificate and key. The ports have all been switched to 443. The external host path of "/u01/registry_certs" is mapped to the "/certs" path inside the container.
#docker rm -vf registry docker run -d \ --name registry \ --restart=always \ -v /u01/volumes/registry:/var/lib/registry \ -v /u01/registry_certs:/certs \ -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.localdomain.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/registry.localdomain.key \ -p 443:443 \ registry:2.7.1
Assuming we have "registry.localdomain" pointing to the correct IP address in the DNS, or in the hosts files for a local test, we can use the registry as following. In the following examples we repeat the previous steps, but this time using the HTTPS enabled registry.
# Place an image in the registry. docker pull oraclelinux:8-slim docker tag oraclelinux:8-slim registry.localdomain/oraclelinux:8-slim docker push registry.localdomain/oraclelinux:8-slim # Remove the local cached images. docker image remove oraclelinux:8-slim docker image remove registry.localdomain/oraclelinux:8-slim # Start a container based on the registry image. docker pull registry.localdomain/oraclelinux:8-slim docker run -d --restart always --name ol8 registry.localdomain/oraclelinux:8-slim
For more information see:
Hope this helps. Regards Tim...