We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Build Artifacts and Deployment Hygiene

A production container should contain what the app needs to run and not much else. Extra tools and files increase image size and give an attacker more to work with.

This Dockerfile builds and runs a Go app in one image:

FROM golang:1.27.0-alpine

WORKDIR /app
COPY . .
RUN go build -o server ./cmd/server
CMD ["./server"]

It copies the entire build context and leaves the compiler, module cache, and source code in the production image. A multi-stage build can compile the binaries separately and copy only runtime artifacts into a smaller final stage:

FROM golang:1.27.0-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -trimpath -o /out/server ./cmd/server

FROM alpine:3.22
WORKDIR /app
COPY --from=build /out/server ./server
USER 10001
CMD ["./server"]

The exact runtime files depend on the app. Explicitly copy only the binaries and assets production needs, and run the process as an unprivileged user.

Running as the unprivileged bearly user limits what a compromised process can do. The user still needs permission to perform Bearly Secure's ordinary runtime work.

Assignment

Bearly Secure's production image contains the whole project and Go toolchain. Replace it with a narrow multi-stage image.

  1. docker build -t bearly-secure .
    docker run --rm --entrypoint id bearly-secure -u
    

Run and submit the CLI tests from the project root.