How-to: build and push Docker images with Kaniko

Brief

Kaniko is a tool to build and push Docker images from within a container or k8s cluster.
Importantly, this is done without a Docker daemon.

For CircleCI builds, Kaniko allows us to build and push Docker images without the Remote Docker engine.

In this how-to guide, we will take a look at how to push images, with Kaniko, to the following:

  • AWS ECR
  • Docker Hub

Before you start

:memo: I am using project environment variables (env vars) for storing credentials for Docker Hub and AWS ECR. Your team may choose to use org contexts instead.

:warning: Docker Layer Caching feature is not compatible for Kaniko builds (since there are no Docker daemons).
Consider using Kanikoโ€™s caching feature instead.

Please also be aware of existing limitations with Kaniko.

AWS ECR

  1. Configure AWS credentials
  2. Define a CircleCI Docker executor job as shown below
jobs:
  kaniko-build-push-aws-ecr:
    # NOTE: Kaniko executor already comes with AWS ECR credential helper installed
    # See https://github.com/GoogleContainerTools/kaniko#pushing-to-amazon-ecr
    # What this means is that, we can just inject AWS credentials.
    # In this example, we set credentials via AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY project env vars
    environment:
      # NOTE: Replace these values as required
      AWS_DEFAULT_REGION: ap-northeast-1
      AWS_REGION: ap-northeast-1
    docker:
      # we use the debug tag since it comes with sh
      - image: gcr.io/kaniko-project/executor:debug
        entrypoint: ""
    steps:
      - checkout
      - run:
          name: Build and Push image
          command: |
            # We pass in AWS credentials and configuration through the AWS_* env vars, via build-arg arguments.
            # See https://github.com/GoogleContainerTools/kaniko/issues/713#issuecomment-557596725
            # NOTE: please replace --destination to your AWS ECR image's URL accordingly
            /kaniko/executor \
                --context "$(pwd)" \
                --dockerfile "$(pwd)/Dockerfile" \
                --build-arg AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION \
                --build-arg AWS_REGION=$AWS_REGION \
                --build-arg AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
                --build-arg AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
                --destination "public.ecr.aws/z1j6a2i1/kelvintaywl/fancy-nginx:${CIRCLE_SHA1}"

Docker Hub

  1. Set up Docker Hub credentials
  2. Define a CircleCI Docker executor job as shown below
jobs:
  kaniko-build-push-docker-hub:
    environment:
      # NOTE: Replace these values as required
      DOCKER_REGISTRY: docker.io
    docker:
      # we use the debug tag since it comes with sh
      - image: gcr.io/kaniko-project/executor:debug
        entrypoint: ""
    steps:
      - checkout
      - run:
          name: add Docker Hub credentials
          command: |
            # NOTE: Docker Hub credentials (DOCKER_LOGIN and DOCKER_PASSWORD env vars)
            # are injected via project env vars
            mkdir -p /kaniko/.docker
            ./config.sh
            mv config.json /kaniko/.docker
      - run:
          name: Build and Push image
          command: |
            /kaniko/executor \
                --context "$(pwd)" \
                --dockerfile "$(pwd)/Dockerfile" \
                --destination "${DOCKER_REGISTRY}/kelvintaywl/fancy-nginx:${CIRCLE_SHA1}"

Important

Note that the Kaniko executor image is only concerned with building and pushing images.
If your job is trying to do more than that, consider splitting the concerns to separate jobs (in the same workflow).

Follow-up

For a working example, do feel free to refer to a public project I have here:

In addition, GitLab also has a great document on using Kaniko on GitLab CI:

I hope this is useful and helpful for anyone trying to use Kaniko on CircleCI :nerd_face:

2 Likes