Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash scripts/docker-build-cache.test.sh
name: Validate Docker build cache configuration
- uses: actions/setup-go@v5
with:
go-version: "^1.24"
Expand All @@ -53,6 +55,7 @@ jobs:
.docker/druid-install-command.sh

prerelease:
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
needs: [unit-tests, integration-tests, validate-api, build]
outputs:
Expand Down
20 changes: 15 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
# syntax=docker/dockerfile:1

FROM golang:bullseye AS builder

ARG VERSION=docker

COPY . .
COPY .docker/entrypoint.sh /entrypoint.sh
WORKDIR /src

WORKDIR /go
COPY go.mod go.sum ./
RUN --mount=type=cache,id=druid-go-mod,target=/go/pkg/mod,sharing=locked \
--mount=type=cache,id=druid-go-build,target=/root/.cache/go-build,sharing=locked \
go mod download && \
go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.5.1

ENV VERSION=${VERSION}

RUN make build
COPY . .
COPY .docker/entrypoint.sh /entrypoint.sh

RUN --mount=type=cache,id=druid-go-mod,target=/go/pkg/mod,sharing=locked \
--mount=type=cache,id=druid-go-build,target=/root/.cache/go-build,sharing=locked \
make build

# The binaries are in ./bin/ directory after build

Expand All @@ -34,7 +44,7 @@ RUN ARCH=$(uname -m) && \
chmod +x /usr/bin/yq

# Copy only the built binaries and entrypoint from builder
COPY --from=builder /go/bin/druid* /usr/bin/
COPY --from=builder /src/bin/druid* /usr/bin/
COPY --from=builder /entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

Expand Down
46 changes: 46 additions & 0 deletions scripts/docker-build-cache.test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOCKERFILE="$SCRIPT_DIR/../Dockerfile"

python3 - "$DOCKERFILE" <<'PY'
from pathlib import Path
import sys

dockerfile = Path(sys.argv[1]).read_text(encoding="utf-8")

if not dockerfile.startswith("# syntax=docker/dockerfile:1\n"):
raise SystemExit("Dockerfile does not opt into BuildKit cache mounts")
if "WORKDIR /src" not in dockerfile:
raise SystemExit("Go module build must run outside GOPATH in /src")
if "COPY --from=builder /src/bin/druid* /usr/bin/" not in dockerfile:
raise SystemExit("Runtime stage does not copy binaries from /src")

dependency_copy = dockerfile.find("COPY go.mod go.sum ./")
source_copy = dockerfile.find("COPY . .")
module_download = dockerfile.find("go mod download")
generator_install = dockerfile.find(
"go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.5.1"
)
version_env = dockerfile.find("ENV VERSION=${VERSION}")

if min(dependency_copy, source_copy, module_download, generator_install, version_env) < 0:
raise SystemExit("Dockerfile is missing the dependency-first Go build layer")
if not dependency_copy < module_download < source_copy:
raise SystemExit("Go modules are not prepared before the full source copy")
if not generator_install < source_copy:
raise SystemExit("oapi-codegen is reinstalled after every source change")
if not generator_install < version_env < source_copy:
raise SystemExit("VERSION invalidates the stable dependency/tool layer")

source_build = dockerfile[source_copy:]
for target in ("target=/go/pkg/mod", "target=/root/.cache/go-build"):
if target not in source_build:
raise SystemExit(f"Source build is missing cache mount {target}")
if "make build" not in source_build:
raise SystemExit("Source build no longer runs the required make build target")
PY

echo "Docker build keeps required work while reusing Go dependency and compiler caches."
Loading