https://garden.io logo
Image Build Caching : configure with GHA calling G...
# 🌱|help-and-getting-started
a
Hi, I'd am trying to configure Garden builds to use registry caching so that builds are faster in CI in situations where the image does not change. I'd like to be able to do this without using the Remote Container Builder since we currently do not share images etc. Just something simple in CI to speed up builds for each team. I know this can easily be done outside of Garden using the
setup-buildx-action@v3
+
build-push-action@v6
(with cache-from, cache-to set). BUT I want to do it using Garden 🙂 Is there a recommended method to get this working (or an example I can look at)? I have tried the following but it seems to work sporadically (sometimes cache hits or misses on builds even if nothing changes). First, I'd like to confirm this method is valid before I troubleshoot any further, but also am open to suggestions/improvements to get this design working. (more info in thread due to message lenght issues
I am building 2 images (app and app2) - the Build Action looks like below for each (other than naming etc)
Copy code
kind: Build
type: container
name: app2
environments: [preview,ci,local]
dependencies: [run.ecr-login] # Note: ecr-login only runs in preview environment, so this dependency will be skipped in ci
source: # define the source path so that builds are based on the app2 folder, assume Dockerfile is in the app2 folder
  path: app2
variables:
  hostname: '${this.name}.${var.baseHostname}' # for local environment hostnames/domains - this is wired up by garden ingress controller on local cluster
spec:
  publishId: "${var.imageRegistry}/${this.name}:${slice(git.commitHash, 0, 7)}" # use short commit hash as tag
  # See project.garden.yaml for env details
  platforms: ${var.platforms}
  extraFlags:
    - "--provenance=false"
    # Add cache configuration for CI environment only (registry cache in CI, inline cache for local/preview)
    # Cache reference matches publishId pattern: ${var.imageRegistry}/${this.name}:buildcache
    # Note: --output=type=docker ensures image is available locally for tagging (required in CI with registry cache)
    - "--output=type=docker"
    - '${environment.name == "ci" ? "--cache-from=type=registry,ref=" + var.imageRegistry + "/" + this.name + ":buildcache" : "--cache-from=type=inline"}'
    - '${environment.name == "ci" ? "--cache-to=type=registry,ref=" + var.imageRegistry + "/" + this.name + ":buildcache,mode=max" : "--cache-to=type=inline"}'
My GHA workflow that is triggered on push (for testing) looks like this:
Copy code
name: Publish/build Image

on:
  push:
    branches:
      - main
      - test-build-cache # temp branch for testing

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      # - name: Build app
      #   uses: garden-io/garden-action@v2
      #   env:
      #     BUILDKIT_PROGRESS: plain
      #     DOCKER_BUILDKIT: 1
      #   with:
      #     log-level: verbose
      #     garden-version: 0.14.9
      #     command: build app --env ci

      # - name: Build app2
      #   uses: garden-io/garden-action@v2
      #   env:
      #     BUILDKIT_PROGRESS: plain
      #     DOCKER_BUILDKIT: 1
      #   with:
      #     log-level: verbose
      #     garden-version: 0.14.9
      #     command: build app2 --env ci

      - name: Publish with Garden
        uses: garden-io/garden-action@v2
        env:
          BUILDKIT_PROGRESS: plain # debug build output
          DOCKER_BUILDKIT: 1 # enable buildkit
        with:
          log-level: verbose
          garden-version: 0.14.9
          command: publish --env ci
I have tried using 2 sep Build steps instead of just Publish (commented out above), but I still get sporadic cache misses on builds even with empty commits. I If anyone has any ideas/pointers to solve this it would be appreciated. I can post more logs info if needed. Thanks!
s
Hi @ancient-island-74119! Thanks for the detailed write-up. When you get cache misses, are you sure that the
publishId
isn't changing? This is using the commit hash rather than the Garden version there. If you were hoping to use Garden's versioning to achieve cache hits, this approach would probably only work if you're using Garden Cloud's caching.
a
thanks @swift-garage-61180 - I took a break from this and am just checking back now to see if there were any responses. I'll dig in again and let you know. hopefully soon... in the meantime, is there a better approach if I wasn't using garden cloud? This approach does use the buildcache (registry cache). I have tried this using just docker buildx actions (not using garden) and it works fine and uses the cache when expected.
Example:
Copy code
name: Publish Image (Direct Docker)

on:
  push:
    branches:
      - main
      - test-build-cache # temp branch for testing

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Fetch full history for commit hash

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
        with:
          driver-opts: |
            image=moby/buildkit:latest

      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Get short commit hash
        id: commit
        run: |
          SHORT_COMMIT=$(git rev-parse --short HEAD)
          echo "short_commit=${SHORT_COMMIT}" >> $GITHUB_OUTPUT
          echo "Using commit hash: ${SHORT_COMMIT}"

      - name: Build and push app (with cache)
        uses: docker/build-push-action@v5
        env:
          BUILDKIT_PROGRESS: plain
          DOCKER_BUILDKIT: 1
        with:
          context: ./app
          file: ./app/Dockerfile
          platforms: linux/amd64
          push: true
          tags: |
            ghcr.io/daysmart/platform-demo/app:${{ steps.commit.outputs.short_commit }}
          cache-from: |
            type=registry,ref=ghcr.io/daysmart/platform-demo/app:buildcache
          cache-to: |
            type=registry,ref=ghcr.io/daysmart/platform-demo/app:buildcache,mode=max
          provenance: false

      - name: Build and push app2 (with cache)
        #... (same as above - removing due to disciord char limit)
20 Views