Open sfllaw opened 3 years ago
Here is a sample devtools/docker/Dockerfile.frontend that works for me:
# Copyright 2021 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# This Dockerfile expects the build context to be the public repo root.
################################################################
FROM golang:1.16.7 AS builder
# Set the working directory outside $GOPATH to ensure module mode is enabled.
WORKDIR /src
# Copy go.mod and go.sum into the container.
# If they don't change, which is the common case, then docker can
# cache this COPY and the subsequent RUN.
COPY go.mod go.sum all.bash /
# Download the dependencies.
RUN go mod download
# Copy the pkgsite repo from local machine into Docker client’s current working
# directory, so that we can use it to build the frontend.
# See .dockerignore at the repo root for excluded files.
COPY . /src
# Build the frontend.
RUN CGO_ENABLED=0 go build -mod=readonly ./cmd/frontend
################################################################
FROM busybox:1.32-musl AS busybox
FROM scratch
WORKDIR app
COPY --from=busybox /bin/sh /bin/
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder src/frontend frontend
COPY static static
COPY third_party third_party
The above Dockerfile as a diff:
diff --git a/devtools/docker/Dockerfile.frontend b/devtools/docker/Dockerfile.frontend
index a35f73da..f17135ac 100644
--- a/devtools/docker/Dockerfile.frontend
+++ b/devtools/docker/Dockerfile.frontend
@@ -6,7 +6,6 @@
################################################################
FROM golang:1.16.7 AS builder
-# If you change the Go version above, change the FROM line below as well.
# Set the working directory outside $GOPATH to ensure module mode is enabled.
WORKDIR /src
@@ -25,13 +24,18 @@ RUN go mod download
COPY . /src
# Build the frontend.
-RUN go build -mod=readonly ./cmd/frontend
+RUN CGO_ENABLED=0 go build -mod=readonly ./cmd/frontend
################################################################
-FROM golang:1.16.7
+FROM busybox:1.32-musl AS busybox
+
+FROM scratch
WORKDIR app
+COPY --from=busybox /bin/sh /bin/
+COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
+
COPY --from=builder src/frontend frontend
COPY static static
COPY third_party third_party
Are you sure scratch
is enough and not something like gcr.io/distroless/static
?
@mitar That is a good question. Since frontend relies on GOPROXY, having the CA certificates baked in to the image might be very nice.
Also, it would probably be best to add an ENTRYPOINT
statement in there: https://github.com/docker-library/official-images#consistency:
If the image only contains the main executable and its linked libraries (ie no shell) then it is fine to use the executable as the
ENTRYPOINT
, since that is the only thing that can run:ENTRYPOINT ["fully-static-binary"] CMD ["--help"]
The most common indicator of whether this is appropriate is that the image Dockerfile starts with
scratch
(FROM scratch
).
Problem
Currently, devtools/docker/Dockerfile.frontend uses the golang image as its base image.
This is inconsistent with modern best practices, where services are typically hosted on the minimal scratch image. The current image has an entire operating system and the Go toolchain included, which is unnecessary because only the frontend and its data are copied in. The frontend doesn’t need an entire OS to run.
Suggested solution
CGO_ENABLED=0
to produce a statically linked binary.FROM scratch
to build the final Docker image.Links
Related: #39827