Faster CI Builds with Docker Remote Caching

Bitbucket Pipelines provides a Docker caching feature that can help improve build times. However, the limitation is that only compressed caches under 1GB are saved and can be used. In this blog, we outline a process showing how you can use compressed caches that are larger than 1GB.

With Docker versions >= 19.03, you can use the BuildKit feature. With BuildKit, you don’t need to keep the cache locally before building the Docker image since it caches each build layer in your image registry. Then, when you build the Docker image, each layer is downloaded as needed during the build.

However, you cannot enable BuildKit for the default Docker service in Bitbucket Pipelines. To enable BuildKit, you'll need to use a self-hosted runner to execute your builds. With a self-hosted runner, you can specify your step to use a custom 'dind', which allows you to use the 'buildkit' feature. With the 'buildkit' feature, turn on the inline layer caching using the BUILDKIT_INLINE_CACHE build argument and use --cache-from while building the image using remote caching.

Here’s how it works:

Define a custom 'dind'

First, define a docker service with docker in the docker image (dind). Since the current docker:dind is already enabled in buildkit by default, you can just use it (as shown below)

definitions:
  services:
    docker:
      image: docker:dind

Then in your Pipeline step, enable BuildKit and turn on inline layer caching using the BUILDKIT_INLINE_CACHE build argument and use --cache-from while building the image using remote caching.

Enable buildkit with DOCKER_BUILDKIT env var and build the image using remote caching

pipelines:
  default:
  - step:
      name: Step 1
      runs-on: self.hosted
      script:
        - export DOCKER_BUILDKIT=1
        - docker build \
          --build-arg BUILDKIT_INLINE_CACHE=1 \
          --cache-from $IMAGE_NAME:$IMAGE_TAG \
          -t $IMAGE_NAME:$IMAGE_TAG .
        - docker push $IMAGE_NAME:$IMAGE_TAG
      services:
        - docker
        
definitions:
  services:
    docker:
      image: docker:dind

Once you’ve configured self-hosted runner using a Docker service with the default BuildKit option enabled, your build times will be faster with Docker remote caching as the Docker image build process will use the cached layers instead of building them everytime from scratch.