Skip to content

Multi-stage Docker builds for Go

Multi-stage builds are a Docker optimization technique used to create smaller, more secure container images for Go applications by separating the build environment from the runtime environment.^[400-devops__09-Scripting-Language__golang__introduction__readme.md]

Architecture

In a multi-stage build, the Dockerfile is divided into distinct sections using FROM statements with unique names (aliases).^[400-devops__09-Scripting-Language__golang__introduction__readme.md]

  • Dev/Build Stage: This stage uses a full-featured image, such as golang:1.15-alpine, which contains the Go compiler and toolchain.^[400-devops__09-Scripting-Language__golang__introduction__readme.md]
  • Runtime Stage: This stage creates a minimal image, typically using a lightweight OS like alpine, that contains only the compiled binary and necessary dependencies.^[400-devops__09-Scripting-Language__golang__introduction__readme.md]

The COPY --from Instruction

The core mechanism of this approach is the COPY --from instruction, which moves artifacts between stages.^[400-devops-09-scripting-language-golang-introduction-part-4commandline-readme.md]

This directive allows the runtime stage to copy the compiled executable (e.g., the binary produced by go build) from the build stage into the final image, leaving behind the source code, build tools, and intermediate files.^[400-devops-09-scripting-language-golang-introduction-part-4commandline-readme.md]

Workflow

A typical build process involves defining a hierarchy of targets:

  1. Development: The first stage often defines a dev target to serve as an active coding environment with mounted volumes.^[400-devops-09-scripting-language-golang-introduction-part-4commandline-readme.md]
  2. Compilation: The build target handles the execution of go build to produce the static binary.^[400-devops-09-scripting-language-golang-introduction-part-4commandline-readme.md]
  3. Final Runtime: The final stage copies the binary to a clean image and sets the entry point.^[400-devops-09-scripting-language-golang-introduction-part-4commandline-readme.md]

Example Configuration

The following Dockerfile demonstrates the separation of concerns, using a build stage to compile the code and a runtime stage to host the application:^[400-devops-09-scripting-language-golang-introduction-part-4commandline-readme.md]

# Build stage
FROM golang:1.15-alpine as build

WORKDIR /videos
COPY ./videos/* /videos/
RUN go build -o videos

# Runtime stage
FROM alpine as runtime
COPY --from=build /videos/videos /usr/local/bin/videos
COPY ./videos/videos.json /
COPY run.sh /
RUN chmod +x /run.sh
ENTRYPOINT [ "./run.sh" ]

Sources

  • 400-devops-09-scripting-language-golang-introduction-part-4commandline-readme.md
  • 400-devops__09-Scripting-Language__golang__introduction__readme.md