DEV Community

Cover image for Build and push a Docker/OCI image with kaniko + GitHub Packages
Hideki Igarashi
Hideki Igarashi

Posted on

Build and push a Docker/OCI image with kaniko + GitHub Packages

GitHub Packages provides a Docker container management platform.

This article introduces how to push an image using it as a repository of kaniko.

kaniko is a tool for Kubernetes, but you can use it without Kubernetes.

By using kaniko, there is a benefit of using the cache with GitHub Packages.

Push image from the local environment

Generate a personal access token

Generate a personal access token to access the registry in your GitHub settings.

The token needs the following scopes:

  • repo
  • write:packages
  • read:packages
  • delete:packages

Create a config.json

Get your GitHub username and token encoded in base64:

$ echo -n username:access_token | base64

Create a config.json file with GitHub package registry hostname and the previous generated base64 string:

{
  "auths": {
    "docker.pkg.github.com": {
      "auth": "xxxxxxxxxxxxxxxxx"
    }
  }
}

Run kaniko

Run kaniko with the config.json.

Also, put the Dockerfile you want to build in the same directory.

The command to execute is as follows:

$ docker run \
  -v $(pwd):/workspace \
  -v $(pwd)/config.json:/kaniko/.docker/config.json:ro \
  gcr.io/kaniko-project/executor:latest \
    --context dir:///workspace/ \
    --dockerfile Dockerfile \
    --destination docker.pkg.github.com/<org>/<repos>/<image>:<tag> \
    --cache=true \
    --cache-repo docker.pkg.github.com/<org>/<repos>/<image>-cache

The cache repository is separate from the destination because GitHub Packages does not support <org>/<repos>/<image>/cache style.

Push image from GitHub Actions

Full example: https://github.com/ganta/example-kaniko-with-github-packages

In this example, the workflow runs under the following conditions:

  • When pushed to a branch except for the master, build an image
  • When pushed to the master branch, add the latest tag and push the image
  • When you push a tag in the version number format, add the tag of that number and push the image

Create two workflows to build and push.

To run the build workflow on a branch excluding master (.github/workflows/build.yml):

on:
  push:
    branches-ignore:
      - master

To run the push workflow on the master branch or a version number format tag (.github/workflows/push.yml):

on:
  push:
    branches:
      - master
    tags:
      - '[0-9]+.[0-9]+.[0-9]+'
      - '[0-9]+.[0-9]+.[0-9]+-*'

Add a step to generate config.json to pass GitHub Packages authentication:

      - name: Generate a config.json
        run: |
          cat <<JSON > config.json
          {
            "auths": {
              "docker.pkg.github.com": {
                "auth": "$(echo -n :${{ secrets.GITHUB_TOKEN }} | base64)"
              }
            }
          }
          JSON
      ...

When using secrets.GITHUB_TOKEN, the user name is not required.

The execution method of kaniko is the same as when executing locally.

For builds, use the --no-push option instead of the--destination option.

      - name: Build an image
        run: |
          docker run \
            -v $(pwd):/workspace \
            -v $(pwd)/config.json:/kaniko/.docker/config.json:ro \
            gcr.io/kaniko-project/executor:latest \
              --context dir:///workspace/ \
              --dockerfile Dockerfile \
              --cache=true \
              --cache-repo docker.pkg.github.com/${GITHUB_REPOSITORY}/${IMAGE_NAME}-cache \
              --no-push

In the case of a push, you can get the tag to attach to the image from the GITHUB_REF environment variable.

      - name: Build and push an image
        run: |
          tag=${GITHUB_REF##*/}

          if [[ ${tag} == master ]]
          then
            tag="latest"
          fi
          echo "tag: ${tag}"

          docker run \
            -v $(pwd):/workspace \
            -v $(pwd)/config.json:/kaniko/.docker/config.json:ro \
            gcr.io/kaniko-project/executor:latest \
              --context dir:///workspace/ \
              --dockerfile Dockerfile \
              --destination docker.pkg.github.com/${GITHUB_REPOSITORY}/${IMAGE_NAME}:${tag} \
              --cache=true \
              --cache-repo docker.pkg.github.com/${GITHUB_REPOSITORY}/${IMAGE_NAME}-cache

Conclusion

In this way, you can smoothly run kaniko with GitHub Packages.

Also, you can use secrets.GITHUB_TOKEN in GitHub Actions, so you don't have to struggle with authentication.

Even if you are not in Kubernetes, you can benefit from caching by using kaniko instead of docker build.

Top comments (0)