Use Docker layer caching with docker-compose build (not just docker)


I spent some time getting my workflows to work with the docker layer caching as described in the blog by Docker: Docker Github Actions - Docker Blog

This works fine for building the images with Docker:

      - name: Set up Docker Buildx
        id: buildx        
        uses: docker/setup-buildx-action@master

      - name: Cache Docker layers
        uses: actions/cache@v2
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-step1-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-

      - name: Build and push images
        uses: docker/build-push-action@v2
          push: false
          builder: ${{ }}
          tags: repo/step1:latest
          file: ./Dockerfile.step1
          context: .
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache

And I have 1 more container build like that (step2).

I have a docker-compose setup to run unit tests & integration tests with a whole bunch of docker-compose specific config around environment variables, volumes, entrypoints, etc.

So I am running these tests using docker-compose. Problem is docker-compose doesn’t use the images built by Docker. I did a lot of searching and googling and tried lots of things, but everything I found doesn’t seem to help to get it to work in GitHub actions.

Latest try (after the docker build steps above):

      - name: Build the stack
        run: COMPOSE_DOCKER_CLI_BUILD=1 docker-compose build

Doesn’t help, docker compose starts rebuilding both containers from scratch. Also doing docker-compose up doesn’t help, it starts pulling the images from docker hub.

Anyone knows the solution? Could be that I’m missing something, but most examples of docker layer caching (with github actions) doesn’t seem to cover docker-compose.

Full workflow and runs here: Docker caching by valentijnscholten · Pull Request #60 · valentijnscholten/django-DefectDojo · GitHub



Added a basic PoC here where I build with docker-build-push action and then use docker-compose up with --no-build

Locally on my machine this works fine. Docker-compose uses the images build by docker. On GitHub actions it doesn’t work. the jobs fails as it says the image is not there.

ok, found the solution. I realized that maybe the docker-build-and-push action didn’t actually do anything with the generated image, i.e. it was not made available to the runner / docker. Turns out this is true and even documented:

Once you know what you’re looking for, it’s easy…

In case the link dies, the solution is to add load: True to the docker-build-and-push action:

- name: Build
        uses: docker/build-push-action@v2
          push: false
          load: true
          tags: valentijn/app:latest
          builder: ${{ }}
          file: ./Dockerfile
          context: .
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache

Note that there’s a bug that makes the cache grow and grow if you do it this way. There’s a fix here.

I struggled to get this working - docker-compose would not pick up on the cache content, in spite of following the suggestions around using the load parameter etc.

However, I did find a 3rd party option that might be suitable for anyone having similar problems to me:

I do recommend using the documented step of pulling images, as the caching was much slower when I omitted it on my first run through. Oddly I found that docker-compose ignored the ignore-pull-failures flag, so I threw in the continue-on-error flag.

- name: Docker Compose pull
     run: docker-compose pull --ignore-pull-failures
     continue-on-error: true

This is not working … I have build args in docker-compose and it is not providing on the builds… Also, the logs doesn’t show any indication…

I would expect that the library called “docker buildx bake | Docker Documentation” buildx bake…

Awesome! It works. Just don’t keep in mind that the tag in Action workflow and specified image name in the docker-compose.yml have to be the same. Otherwise, it rebuilds the image instead of using cache.