This page documents how to install a private repository and, in particular, how to run the repository within a docker swarm. When using docker, sometimes it is necessary to make changes to the images, such that it becomes imperative to be able to deploy at least a minimal docker repository, that will run internally and tasked to serve modified images.
The registry compose file is the following:
version: '3.7' services: registry: image: registry:2.7 ports: - 5000:5000 environment: REGISTRY_AUTH: htpasswd REGISTRY_AUTH_HTPASSWD_REALM: Registry REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /registry-data volumes: - /mnt/docker/data/registry/auth:/auth - /mnt/docker/data/registry/registry-data:/registry-data
and the host folder /mnt/docker/data/registry/auth
mapped on the inside of the docker container to /auth
should contain a file named registry.password
that is generated using htpasswd
obtained from the apache2-utils
package:
htpasswd -Bc registry.password
Running the command allows the creation of a username and password for the registry that can be used when pushing images.
Given that the registry is only internal, and that the swarm would have to pull containers from it, it makes sense to run the registry without TSL/SSL. In order to do that, on every node in the swarm, docker has to be told which registry is insecure, by editing the /etc/docker/daemon.json
and adding a line:
"insecure-registries": [ "192.168.10.0/24" ]
such that any registry found at the address mask 192.168.10.0/24
will be accessed using HTTP instead of HTTPs. Intuitively, the address mask 192.168.10.0/24
should over the docker swarm.
With the file modified, the docker daemon has to be restarted on all nodes within the swarm:
systemctl restart docker
Pushing to the newly created private registry is tricky because the syntax of the containers is well-defined. As a general overview, the format is:
docker login <REGISTRY_HOST>:<REGISTRY_PORT> docker tag <IMAGE_ID> <REGISTRY_HOST>:<REGISTRY_PORT>/<APPNAME>:<APPVERSION> docker push <REGISTRY_HOST>:<REGISTRY_PORT>/<APPNAME>:<APPVERSION>
So, as an example, assuming that:
docker
and port 5000
,then the commands will be:
docker login docker:5000 docker tag overleaf-full docker:5000/overleaf:latest docker push docker:5000/overleaf:latest
Similarly, in order to directly reference the repository, docker containers can be built by following the naming convention. For instance, here is a command that builds caddy from a docker file and tags the built image with the correct reference to the local repository:
docker build -t docker:5000/caddy:latest
Then by following the commands above, the built image can be pushed to the local repository.
Now that the new image has been created, following the example, the full image name docker:5000/overleaf:latest
can be referenced from within a docker compose file as the name stands.
Given that the image name is semantically well-defined, even when deployed to a swarm, the nodes will try contacting the host docker
on port 5000
in order to retrieve the application overleaf
at version latest
just by observing the image name.
Conversely, images that are not within the private repository will be pulled from the other repositories by following their names.