The simple power of Docker Multi-Stage builds

written on 2025-01-08

Ever needed to combine multiple Docker images? Public images from the Docker Hub are mostly good at exactly one thing. But often your application consists of multiple technologies. You have a Java backend, but also need NodeJS to transpile and bundle your TypeScript frontend? If you use a full CI/CD environment, like on GitLab or GitHub, you can run multiple tasks and assembly the artifacts into a final image. But that is a big step up from the simplicity of a single Dockerfile.

  • you cannot run the build locally anymore
  • you cannot easily use a git push deployment anymore, with the convenient GitOps hosters, like Fly.io, Heroku, or Dokku, which work from a single Dockerfile directly from a git repository

This is where Docker Multi-Stage builds really shine.

Example Dockerfile

# Run frontend build in a temporary node image:
FROM node:22 AS builder

COPY . /tmp/app
WORKDIR /tmp/app/ui
RUN npm ci
RUN npm run build

# Create the actual application image:
FROM python:3.11
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv

WORKDIR /usr/src/app

COPY . .

# Install dependencies
RUN uv sync

# Fetch the frontend build artifacts from the builder image stage
COPY --from=builder /tmp/app/static ./static

EXPOSE 5000
CMD [ "uv", "run", "gunicorn", "server:app", "--bind", "0.0.0.0:5000"]

Benefits

This build produces 1 single docker image, but during the build, it relies on 3 different images:

  • The node image is used to create a throw-away container in which we run the frontend build
  • We need a binary from the official image released for the uv package manager (this is much more convenient than some wget and tar -xzvf combination)
  • Finally, we want the python image as the base for our application

The core elements are multiple FROM statements to introduce multiple stages, and COPY --from to access results from these other stages.

By using Docker Multi-Stage builds, you can keep your setup simple while leveraging the full power of multiple environments in a single image.