World map

 

BM: Baca dalam Bahasa Melayu

World D2: Recipes

Choose a base image

You will learn: how alpine, slim, distroless and hardened bases change size and safety.

Checked with Docker Engine 29 on 31 Oct 2026

The problem

The same diary page is built twice: on nginx:latest (Debian) and on nginx:1.30-alpine. docker images shows the Debian one is more than twice as big. Docker transcript: $ docker build -t diary:debian . [+] Building 0.1s (7/7) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 111B 0.0s => [internal] load metadata for docker.io/library/nginx:latest 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [1/2] FROM docker.io/library/nginx:latest@sha256:5ab5b0b01097420873a3f 0.0s => => resolve docker.io/library/nginx:latest@sha256:5ab5b0b01097420873a3f 0.0s => [internal] load build context 0.0s => => transferring context: 154B 0.0s => [2/2] COPY index.html /usr/share/nginx/html/ 0.0s => exporting to image 0.1s => => exporting layers 0.0s => => exporting manifest sha256:1822000cfb064931374547d3acfd3d2db20f443b8 0.0s => => exporting config sha256:ae4578166d01a725060bb2956f4b1eb8bb2e0d4a2c1 0.0s => => exporting attestation manifest sha256:263a71b840128e95ff9dc22892f06 0.0s => => exporting manifest list sha256:39454aebe9fe6344eac20daa9de63e3e4645 0.0s => => naming to docker.io/library/diary:debian 0.0s => => unpacking to docker.io/library/diary:debian 0.0s $ docker build --build-arg BASE=nginx:1.30-alpine -t diary:alpine . [+] Building 0.1s (7/7) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 111B 0.0s => [internal] load metadata for docker.io/library/nginx:1.30-alpine 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [1/2] FROM docker.io/library/nginx:1.30-alpine@sha256:0e52bd054126cdc0 0.0s => => resolve docker.io/library/nginx:1.30-alpine@sha256:0e52bd054126cdc0 0.0s => [internal] load build context 0.0s => => transferring context: 154B 0.0s => [2/2] COPY index.html /usr/share/nginx/html/ 0.0s => exporting to image 0.1s => => exporting layers 0.0s => => exporting manifest sha256:507252b8915bf4cf4381c15ebf1e7c4a8e4006782 0.0s => => exporting config sha256:d2cfb7e3f8ad6df59596091ba88392820504d809f2d 0.0s => => exporting attestation manifest sha256:27c17ccb04c15651c1207850939a0 0.0s => => exporting manifest list sha256:15f15d8b01bb011e218e5d2ba55eaf961778 0.0s => => naming to docker.io/library/diary:alpine 0.0s => => unpacking to docker.io/library/diary:alpine 0.0s $ docker images diary i Info → U In Use IMAGE ID DISK USAGE CONTENT SIZE EXTRA diary:alpine 15f15d8b01bb 92.6MB 26.1MB diary:debian 39454aebe9fe 241MB 63.9MB

Your laptop~/diary

  • No open hatches

Lunchboxes (containers)

  • No containers yet

Frozen packs (images)

  • nginx:1.30-alpine8 layers · 93.5MB
  • nginx:latest7 layers · 243MB

0 containers (0 running), 2 images, 0 lockers.

Same page, same recipe, two bases. One pack is more than twice as big. Which base would you ship?

Watch

Tap each point on the timeline.

The base image: The ready-made pack your recipe starts from. It is the FROM line. is the FROM line: the pack you start from. Tap each one, from biggest to smallest.

Try it

Shrink the API’s meal pack below 200MB. Swap the base and try a build stage.

Shrink the meal pack under 200MB. Every button is a real trick.

Image size 1.36GB

Target: 200MBStart: 1.36GB

Base image

Recipe tricks

Dockerfile

FROM node:24
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build
CMD ["node", "dist/server.js"]

Predict

You ship on distroless: A base with only what the app needs to run. No shell, no package manager.. Then you type docker exec -it api sh to look around. What happens?

Pick one answer.

Check

bash
docker run --rm gcr.io/distroless/static-debian13:nonroot sh
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: exec: "sh": executable file not found in $PATH
Run 'docker run --help' for more information
docker run with sh on a distroless image fails: exec sh: executable file not found in $PATH.

Real error: executable file not found in $PATH. Plain words: there is no sh in this pack. That is the point.

Check

Which base fits?

Drag a card into a box. Or tap the card, then tap the box.

        You did it!

        You can now pick a base by size, tools and safety.

        Go deeper (optional)

        Docker Hardened Images live at dhi.io. Log in with your free Docker account, then pull, like dhi.io/python:3.13. They come with an SBOM and signed provenance (World D5). Distroless and hardened bases pair well with a build stage.

        Real mission

        1. docker pull node:24-alpine
        2. docker images

        0 of 3 steps done · Your ticks are saved.