Browse Source

More Dockerfile best practices

* Use mounts for RUN commands to avoid creating extra layers
* Use built-in platform support

Signed-off-by: Christopher Crone <[email protected]>
Christopher Crone 5 years ago
parent
commit
247fa56ee1
2 changed files with 35 additions and 46 deletions
  1. 30 38
      Dockerfile
  2. 5 8
      Makefile

+ 30 - 38
Dockerfile

@@ -1,66 +1,58 @@
 # syntax = docker/dockerfile:experimental
 ARG GO_VERSION=1.14.3-alpine
-ARG GOLANGCI_LINT_VERSION=1.27.0
+ARG GOLANGCI_LINT_VERSION=v1.27.0-alpine
 
-FROM golang:${GO_VERSION} AS base
-ARG TARGET_OS=unknown
-ARG TARGET_ARCH=unknown
-ARG PWD=/api
+FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS base
+WORKDIR /api
 ENV GO111MODULE=on
-
-RUN apk update && apk add -U docker make
-
-WORKDIR ${PWD}
-ADD go.* ${PWD}
+RUN apk add --no-cache \
+    docker \
+    make \
+    protoc
+COPY go.* .
 RUN go mod download
-ADD . ${PWD}
-
-FROM golang:${GO_VERSION} AS protos-base
-ARG TARGET_OS=unknown
-ARG TARGET_ARCH=unknown
-ARG PWD=/api
-ENV GO111MODULE=on
-
-RUN apk update && apk add protoc make
 
+FROM base AS make-protos
 RUN go get github.com/golang/protobuf/[email protected]
-
-WORKDIR ${PWD}
-ADD go.* ${PWD}
-ADD . ${PWD}
-
-FROM protos-base AS make-protos
+COPY . .
 RUN make -f builder.Makefile protos
 
-FROM golangci/golangci-lint:v${GOLANGCI_LINT_VERSION}-alpine AS lint-base
+FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION} AS lint-base
 
 FROM base AS lint
-COPY --from=lint-base /usr/bin/golangci-lint /usr/bin/golangci-lint
 ENV CGO_ENABLED=0
-RUN --mount=id=build,type=cache,target=/root/.cache/go-build \
-    --mount=id=lint,type=cache,target=/root/.cache/golangci-lint \
+COPY --from=lint-base /usr/bin/golangci-lint /usr/bin/golangci-lint
+RUN --mount=target=. \
+    --mount=type=cache,target=/root/.cache/go-build \
+    --mount=type=cache,target=/root/.cache/golangci-lint \
     make -f builder.Makefile lint
 
 FROM base AS make-cli
-RUN --mount=id=build,type=cache,target=/root/.cache/go-build \
-    GOOS=${TARGET_OS} \
-    GOARCH=${TARGET_ARCH} \
-    make -f builder.Makefile cli
+ENV CGO_ENABLED=0
+ARG TARGETOS
+ARG TARGETARCH
+RUN --mount=target=. \
+    --mount=type=cache,target=/root/.cache/go-build \
+    GOOS=${TARGETOS} \
+    GOARCH=${TARGETARCH} \
+    make BINARY=/out/docker -f builder.Makefile cli
 
 FROM base AS make-cross
-RUN --mount=id=build,type=cache,target=/root/.cache/go-build \
-    make -f builder.Makefile cross
+RUN --mount=target=. \
+    --mount=type=cache,target=/root/.cache/go-build \
+    make BINARY=/out/docker  -f builder.Makefile cross
 
 FROM scratch AS protos
 COPY --from=make-protos /api/protos .
 
 FROM scratch AS cli
-COPY --from=make-cli /api/bin/* .
+COPY --from=make-cli /out/* .
 
 FROM scratch AS cross
-COPY --from=make-cross /api/bin/* .
+COPY --from=make-cross /out/* .
 
 FROM base as test
 ENV CGO_ENABLED=0
-RUN --mount=id=build,type=cache,target=/root/.cache/go-build \
+RUN --mount=target=. \
+    --mount=type=cache,target=/root/.cache/go-build \
     make -f builder.Makefile test

+ 5 - 8
Makefile

@@ -32,16 +32,13 @@ export DOCKER_BUILDKIT=1
 all: cli
 
 protos: ## Generate go code from .proto files
-	@docker build . \
-	--output type=local,dest=./protos \
-	--target protos
+	@docker build . --target protos \
+	--output type=local,dest=./protos
 
 cli: ## Compile the cli
-	@docker build . \
-	--output type=local,dest=./bin \
-	--build-arg TARGET_OS=${GOOS} \
-	--build-arg TARGET_ARCH=${GOARCH} \
-	--target cli
+	@docker build . --target cli \
+	--platform local \
+	--output type=local,dest=./bin
 
 e2e-local: ## Run End to end local tests
 	go test -v ./tests/e2e ./moby/e2e