Table of Contents

About

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

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.

Insecure Tweaks

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 Registry

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:

then the commands will be:

docker login docker:5000
docker tag overleaf-full docker:5000/overleaf:latest
docker push docker:5000/overleaf:latest

Building Containers

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.

Referencing the New Image

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.