Skip to content
Posts

GitHub container registry example

Posted on:July 1, 2023 at 11:17 AM

GitHub Packages hosts a Docker container registry at ghcr.io. I have experimented with publishing and consuming container images from GitHub Actions.

GithHub Packages experiment

GitHub Packages include container registry running at ghcr.io. To try it out simple ruby cli script was created and packaged into single purpose container image published to ghcr.io.

Ruby cli scirpt - http-monitor runs series of http get request to a given url measuring response times and calculating average response time.

GitHub repo https://github.com/tsertkov/http-monitor was linked to a http-monitor package on GitHub as described in the documentation to make it possible publishing container image and pulling it from docker repository ghcr.io/tsertkov/http-monitor as a package.

Logging into github packages docker registry at ghcr.io

The GitHub Actions environment must log into the ghcr.io Docker registry using the secrets.GITHUB_TOKEN token before pulling and pushing images.

A custom script step can be used to log into the Docker registry:

- name: Log in to registry
  run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin

or docker/login-action action:

- name: Log in to docker registry
  uses: docker/login-action@v2
  with:
    registry: ${{ env.REGISTRY }}
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}

Publihsing a container image from GitHub Actions

Building and publishing to the GitHub Packages Docker registry, using Actions cache, is very simple with the docker/build-push-action action.

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

...

- name: Image meta
  id: meta
  uses: docker/metadata-action@v4
  with:
    images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Build and push demo container image to registry
  uses: docker/build-push-action@v4
  with:
    cache-from: type=gha
    cache-to: type=gha,mode=max
    push: true
    context: .
    tags: ${{ steps.meta.outputs.tags }}
    labels: ${{ steps.meta.outputs.labels }}

Achieving the same result with a custom script step, which provides full control over the workflow, is also straightforward.

- name: Push image
  run: |
    IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
    IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
    VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
    [ "$VERSION" == "main" ] && VERSION=latest
    echo IMAGE_ID=$IMAGE_ID
    echo VERSION=$VERSION
    docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
    docker push $IMAGE_ID:$VERSION

Using a container image from GitHub Actions

The published container image is later used in a separate workflow from GitHub Actions.

steps:
  - name: Log in to registry
    run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin
  - name: Run docker container
    run: docker run --rm -t ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME:latest "${{ inputs.url }}" "${{ inputs.time }}" "${{ inputs.sleep_interval }}"

Dotfiles docker image

Following the initial http-monitor experiment, the CI for dotfiles was updated to build and publish docker image with dotfiles demonstration environment.

You can see the package in action and explore dotfiles from within an isolated container without installing anything other then Docker:

docker run --rm -it ghcr.io/tsertkov/dotfiles:master