Adding a Local Docker Registry

This entry is part 2 of 3 in the series Self-Hosted GitHub Runners: Learn as I Go (LAIG)

Self-Hosted GitHub Runners: Learn as I Go (LAIG)

Local Self-Hosted Runner using Docker Compose

Adding a Local Docker Registry

Add Self-Hosted Apache Maven Registry

In this post, we build on the work covered in previous post Local Self-Hosted Runners using Docker Compose, by adding a local docker registry to the stack; this will allow workflow jobs executing on our self-hosted runner to push/pull images to/from the registry.

Docker Compose Stack With Dkr Registry 1

Docker Daemon – Enable Insecure Registry

By default, connections to insecure registries, originating from the daemon, are forbidden. This behaviour can be overridden via a configuration change to /etc/docker/daemon.json.

The DIND image, created as part of initial post, included a version of the daemon.json. Assuming a registry hostname:port of registry:5000, add the following to the file.

{
    "hosts": [
        "unix:///var/run/docker.sock"
    ]
    ,"insecure-registries": ["registry:5000"]
}

For the changes to take effect, the image will need to be rebuilt.

$ cd $HOME/ubuntu-self-hosted-gh-runner
$ docker buildx build --load -t ubuntu-self-hosted-gh-runner:latest \
  --build-arg RUNNER_VERSION=$(curl -s -L -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" "https://api.github.com/repos/actions/runner/releases/latest" | jq -r '.tag_name' | cut -c 2-) \
  --build-arg RUNNER_USER="runner" \
  --build-arg CONTEXT_ROOT_PATH="jammy_stable" \
  -f jammy_stable/Dockerfile .

Add Docker Registry Container to Docker Compose Stack

The official Distribution registry image available at Docker Hub will allow us to quickly add a local registry service to the docker compose stack.

Below is the revised version of the docker-compose.yml, which includes the service definition for the local registry.

version: "3.8"

services:
  self-hosted-runner:
    image: ubuntu-self-hosted-gh-runner:latest
    container_name: self-hosted-runner
    privileged: true
    volumes:
      - var-lib-docker:/var/lib/docker
    networks:
      - local-net
    environment:
      - REPO_OWNER=my-git-username
      - REPOSITORY=self-hosted-local-infra-test
      - RUNNER_ADMIN_TOKEN=<classic personal access token>
      - RUNNER_LABELS={"labels":["self-hosted","jammy-amd64"]}
      - RUNNER_NAME=self-hosted-jammy-amd64
      - RUNNER_CONFIG_ARGS=--unattended --replace --disableupdate --no-default-labels
      
  registry:
    image: registry:latest
    container_name: registry
    hostname: registry
    volumes:
      - ./auth:/auth
      - var-lib-registry:/var/lib/registry     
    ports:
      - "5000:5000"
    networks:
      - local-net
    environment:
      - REGISTRY_AUTH=htpasswd
      - REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm"
      - REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
      - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry

networks:
  local-net:
    name: local-net

volumes:
  var-lib-docker:
    name: var-lib-docker
  var-lib-registry:
    name: var-lib-registry

The host:container volume mount for the registry service includes the following:

volumes:
  - ./auth:/auth

This allows us to generate credentials into host location ./auth for the registry container.

Configure Docker Registry Credentials

Credentials can be generated using the htpasswd utility.

To create a registry username/password of reguser/regpass :

$ docker run --entrypoint htpasswd httpd:2 -nbB reguser regpass > $PWD/auth/htpasswd

Testing

Bring up the compose stack:

$ docker compose up -d

Accessing the Registry from the Host Machine

To access the registry from our host machine, we use endpoint http://localhost:5000 with the credentials we created earlier.

$ docker login -u reguser -p regpass http://localhost:5000

A successful login returns:

WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /home/lts/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

Test Image Push from Host Machine to Registry

Pull an image from Docker Hub:

$ docker pull hello-world:latest

latest: Pulling from library/hello-world
...
...

Tag the image with local registry tag:

$ docker tag hello-world:latest localhost:5000/hello-world:latest

Push:

$ docker push localhost:5000/hello-world:latest

The push refers to repository [localhost:5000/hello-world]
ac28800ec8bb: Pushed
...
...

Test Access to Registry from Self-Hosted GitHub Runner

To ensure workflows executing on our self-hosted runner can access the local registry, we can use the following workflow.

name: Self-hosted Runner to Local Docker Registry test

on:
  push:

env:
  local-registry: "http://registry:5000"
## Hard coded for demo only, use repository secrets in all other cases
  registry-username: reguser
  registry-password: regpass

jobs:
  test-local-registry:
    runs-on: [self-hosted, jammy-amd64]
    steps:
      - name: Pull a test image from Docker Hub
        id: pull-test-img
        run: |
          docker pull docker.io/library/hello-world:latest

      - name: Prepare test image for upload to local registry
        id: tag-test-img
        run: |
          docker tag docker.io/library/hello-world:latest registry:5000/hello-world:latest

      - name: Login to local registry
        id: login
        uses: docker/login-action@v3
        with:
          registry: ${{ env.local-registry }}
          username: ${{ env.registry-username }}
          password: ${{ env.registry-password }}

      - name: Push the to local registry
        id: push-to-local
        run: |
          docker push registry:5000/hello-world:latest

The workflow should complete successfully with the following output.

Self Hosted To Local Registry Test Pull And Tag
Self Hosted To Local Registry Test Push To Local Registry

Self-Hosted GitHub Runners: Learn as I Go (LAIG)

Local Self-Hosted Runner using Docker Compose Add Self-Hosted Apache Maven Registry