From 3e9cc1a7d697b64690a8772fe0ec8e84e34ebf6c Mon Sep 17 00:00:00 2001 From: Lam Tran Date: Wed, 5 Jul 2023 23:01:00 +0700 Subject: [PATCH] refactor(flagd): update build.Dockerfile with buildkit caching (#724) ## This PR updates `flagd/build.Dockerfile` with changes: - use less layers (from 7 to 2) - leverage buildkit features: cache (go mod, go build) and bind ### Related Issues ### Notes - This change is motivated from the new command of docker: `docker init` (reference: https://docs.docker.com/engine/reference/commandline/init/#example-of-selecting-go) ### Follow-up Tasks ### How to test ``` $ docker build . -f ./flagd/build.Dockerfile -t flagd [+] Building 17.3s (12/12) FINISHED docker:orbstack => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load build definition from build.Dockerfile 0.0s => => transferring dockerfile: 1.74kB 0.0s => [internal] load metadata for gcr.io/distroless/static:nonroot 0.5s => [internal] load metadata for docker.io/library/golang:1.20-alpine 1.2s => [builder 1/4] FROM docker.io/library/golang:1.20-alpine@sha256:fd9d9d7194ec40a9a6ae89fcaef3e47c47de7746dd5848ab5343695dbbd09f8c 0.0s => [internal] load build context 0.0s => => transferring context: 8.07kB 0.0s => CACHED [stage-1 1/3] FROM gcr.io/distroless/static:nonroot@sha256:9ecc53c269509f63c69a266168e4a687c7eb8c0cfd753bd8bfcaa4f58a90876f 0.0s => CACHED [builder 2/4] WORKDIR /src 0.0s => CACHED [builder 3/4] RUN --mount=type=cache,target=/go/pkg/mod/ --mount=type=bind,source=./core/go.mod,target=./core/go.mod --mount=type=bind,s 0.0s => [builder 4/4] RUN --mount=type=cache,target=/go/pkg/mod/ --mount=type=cache,target=/root/.cache/go-build --mount=type=bind,source=./core,targe 15.9s => [stage-1 2/3] COPY --from=builder /bin/flagd-build . 0.0s => exporting to image 0.1s => => exporting layers 0.1s => => writing image sha256:ccfeaee26cdeb83fcdd70408d372f9dc382d028eb53773f062f079bdb6ff4a40 0.0s => => naming to docker.io/library/flagd 0.0s $ docker run flagd version ______ __ ________ _______ ______ /_____/\ /_/\ /_______/\ /______/\ /_____/\ \::::_\/_\:\ \ \::: _ \ \\::::__\/__\:::_ \ \ \:\/___/\\:\ \ \::(_) \ \\:\ /____/\\:\ \ \ \ \:::._\/ \:\ \____\:: __ \ \\:\\_ _\/ \:\ \ \ \ \:\ \ \:\/___/\\:.\ \ \ \\:\_\ \ \ \:\/.:| | \_\/ \_____\/ \__\/\__\/ \_____\/ \____/_/ ``` Signed-off-by: Lam Tran Co-authored-by: Lam Tran Co-authored-by: Todd Baert --- flagd/build.Dockerfile | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/flagd/build.Dockerfile b/flagd/build.Dockerfile index a3b236099..788b92648 100644 --- a/flagd/build.Dockerfile +++ b/flagd/build.Dockerfile @@ -2,33 +2,40 @@ # Build the manager binary FROM --platform=$BUILDPLATFORM golang:1.20-alpine AS builder -WORKDIR /workspace +WORKDIR /src + ARG TARGETOS ARG TARGETARCH ARG VERSION ARG COMMIT ARG DATE -# Copy source code -COPY flagd/ flagd -COPY core/ core - -# Setup go workspace -RUN go work init -RUN go work use ./flagd -RUN go work use ./core - -# Go get dependencies -RUN cd flagd && go mod download +# Download dependencies as a separate step to take advantage of Docker's caching. +# Leverage a cache mount to /go/pkg/mod/ to speed up subsequent builds. +# Leverage bind mounts to go.sum and go.mod to avoid having to copy them into +# the container. +RUN --mount=type=cache,target=/go/pkg/mod/ \ + --mount=type=bind,source=./core/go.mod,target=./core/go.mod \ + --mount=type=bind,source=./core/go.sum,target=./core/go.sum \ + --mount=type=bind,source=./flagd/go.mod,target=./flagd/go.mod \ + --mount=type=bind,source=./flagd/go.sum,target=./flagd/go.sum \ + go work init ./core ./flagd && go mod download -# # Build -RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -ldflags "-X main.version=${VERSION} -X main.commit=${COMMIT} -X main.date=${DATE}" -o flagd-build flagd/main.go +# Build the application. +# Leverage a cache mount to /go/pkg/mod/ to speed up subsequent builds. +# Leverage a bind mount to the current directory to avoid having to copy the +# source code into the container. +RUN --mount=type=cache,target=/go/pkg/mod/ \ + --mount=type=cache,target=/root/.cache/go-build \ + --mount=type=bind,source=./core,target=./core \ + --mount=type=bind,source=./flagd,target=./flagd \ + CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -ldflags "-X main.version=${VERSION} -X main.commit=${COMMIT} -X main.date=${DATE}" -o /bin/flagd-build flagd/main.go # # Use distroless as minimal base image to package the manager binary # # Refer to https://github.com/GoogleContainerTools/distroless for more details FROM gcr.io/distroless/static:nonroot WORKDIR / -COPY --from=builder /workspace/flagd-build . +COPY --from=builder /bin/flagd-build . USER 65532:65532 ENTRYPOINT ["/flagd-build"]