Hands-On LabIntermediate

Optimize Docker Images with Multi-Stage Builds

Refactor a bloated single-stage Node.js Dockerfile into a multi-stage build and shrink the production image by over 90 percent.

45 minEstimated time
4Guided steps
AutoVerification
IsolatedSandbox
Optimize Docker Images with Multi-Stage Builds

Lab overview

A Docker image is more than the application that runs inside it. By default, it also carries every compiler, package manager, dev dependency, and intermediate file that was needed to assemble the app, even though none of that is required to actually run it in production. The result is bloated images that are slow to pull on cold nodes, expensive to store in registries, and packed with a wide attack surface of tools an intruder can pivot through. Multi-stage builds solve this problem by letting a single Dockerfile describe two distinct phases: a heavy "builder" stage that installs SDKs and compiles or installs dependencies, and a lean "runtime" stage that copies only the finished artifacts into a minimal base image like alpine, distroless, or scratch. The Open Container Initiative reports that images built with multi-stage workflows ship with roughly 40 percent fewer known vulnerabilities than equivalent single-stage builds, on top of dramatic size reductions of 80 to 99 percent across common runtimes.

In this lab, you will start with a deliberately bloated single-stage Node.js Express image and refactor it into a multi-stage Dockerfile. You will use FROM ... AS builder to install production dependencies in a build stage, COPY --from=builder to cherry-pick only those artifacts into a runtime stage, and then switch the runtime base to a distroless image. By the end you will be able to evaluate base-image trade-offs (Debian versus Alpine versus distroless) and apply the multi-stage pattern to your own services.

Objectives

By completing this intermediate lab, you will be able to:

  • Build the provided single-stage Dockerfile and measure the bloated image footprint with docker image ls.
  • Refactor the Dockerfile into a two-stage build using FROM ... AS builder and a minimal runtime stage.
  • Use COPY --from=builder to copy only production node_modules and source into the final image.
  • Swap the runtime base image to node:22-alpine and compare the content size with the single-stage image.
  • Move the runtime base to a distroless Node image and choose the right trade-off for production.

Who is this lab for?

This lab is designed for:

  • Developers who can already write a basic Dockerfile and want to ship smaller, more secure production images.
  • Platform engineers tuning their registry footprint and node-pull-time SLOs.
  • Security-minded engineers reducing the attack surface of their container fleet.

Verified against your live environment

An automated validation engine inspects your actual resources and configurations as you work. Completion means the task was performed, not multiple choice, real-world proficiency.

[CHECK] validation_activelive
Inspecting deployed resources...
Verifying configuration state...
✓ Step requirements satisfied

More labs like this

Related reading

PremiumIncluded in Premium
Duration
45 min
Steps
4

Environment

Dedicated VM IDE

Every lab includes

  • Real environment, pre-credentialed
  • Automated checks on every step
  • Isolated sandbox, auto cleanup
  • AI-recommended next steps

Lab curriculum

  1. 01

    Getting Started with Docker IDE

  2. 02

    Build and Measure the Bloated Single-Stage Image

    1 automated check

  3. 03

    Refactor the Dockerfile into a Multi-Stage Build

    1 automated check

  4. 04

    Shrink the Runtime Image with a Minimal Base

    1 automated check

Skills validated

DockerDockerfile

Not the lab you were looking for?

Browse 200+ hands-on labs across AWS, Azure, Kubernetes, Docker, and cloud security.

Explore the catalog