World map

 

BM: Baca dalam Bahasa Melayu

World D2: Recipes

Kek lapis: layers and cache

You will learn: why the order of your recipe lines makes builds fast or slow.

Checked with Docker Engine 29 on 31 Oct 2026

The problem

You change one word in server.js. The build runs npm ci again, and you wait two minutes. Why?

Pick one answer.

Watch

The second build changes style.css. WORKDIR and COPY index.html say CACHED. COPY style.css bakes again. Docker transcript: $ docker build -t diary:1.0 . [+] Building 0.1s (9/9) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 135B 0.0s => [internal] load metadata for docker.io/library/nginx:1.30-alpine 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 50B 0.0s => [1/4] FROM docker.io/library/nginx:1.30-alpine@sha256:0e52bd054126cdc0 0.0s => => resolve docker.io/library/nginx:1.30-alpine@sha256:0e52bd054126cdc0 0.0s => [2/4] WORKDIR /usr/share/nginx/html 0.0s => [internal] load build context 0.0s => => transferring context: 208B 0.0s => [3/4] COPY index.html . 0.0s => [4/4] COPY style.css . 0.0s => exporting to image 0.1s => => exporting layers 0.0s => => exporting manifest sha256:415f10199345cc337dd68e80758f75941ce3e3e49 0.0s => => exporting config sha256:ee01a8155259f6e2486f1965e07648f6d9bd9b754d3 0.0s => => exporting attestation manifest sha256:924620499159e7dfcde766051b335 0.0s => => exporting manifest list sha256:a624056884c4c0ffc6aa2f49b7f7a2214640 0.0s => => naming to docker.io/library/diary:1.0 0.0s => => unpacking to docker.io/library/diary:1.0 0.0s $ echo "body { color: hotpink; }" > style.css $ docker build -t diary:1.1 . [+] Building 0.1s (9/9) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 135B 0.0s => [internal] load metadata for docker.io/library/nginx:1.30-alpine 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 50B 0.0s => [1/4] FROM docker.io/library/nginx:1.30-alpine@sha256:0e52bd054126cdc0 0.0s => => resolve docker.io/library/nginx:1.30-alpine@sha256:0e52bd054126cdc0 0.0s => CACHED [2/4] WORKDIR /usr/share/nginx/html 0.0s => [internal] load build context 0.0s => => transferring context: 211B 0.0s => CACHED [3/4] COPY index.html . 0.0s => [4/4] COPY style.css . 0.0s => exporting to image 0.1s => => exporting layers 0.0s => => exporting manifest sha256:88ebfc2dd16e6de6ca7dec45b7030cab18e4d0d5f 0.0s => => exporting config sha256:f932de8330ca850535196b0c948718597b1ef1368c2 0.0s => => exporting attestation manifest sha256:47f2c7f332b856661a324838d3251 0.0s => => exporting manifest list sha256:403fa10c72327feadc6983d91f180fc01a0d 0.0s => => naming to docker.io/library/diary:1.1 0.0s => => unpacking to docker.io/library/diary:1.1 0.0s

Your laptop~/diary

  • No open hatches

Lunchboxes (containers)

  • No containers yet

Frozen packs (images)

  • nginx:1.30-alpine8 layers · 93.5MB

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

Each recipe line bakes one layer: One layer of kek lapis. Change one, and every layer above it is baked again., like kek lapis. Docker keeps old layers. Change style.css: only its layer and the layers on top bake again. The rest say CACHED.

Try it

This recipe bakes npm ci again after every code change. Move the lines so it stays CACHED when server.js changes.

Each recipe line adds one cake layer. Put the lines in a good order, then build.

Dockerfile (the recipe)

  1. FROM node:24-alpine
  2. WORKDIR /app
  3. COPY . .
  4. COPY package.json package-lock.json ./
  5. RUN npm ci --omit=dev
  6. CMD ["node", "server.js"]

You built it once. Next, you change server.js.

The cake (your image)

  1. CMD ["node", "server.js"]0B
  2. RUN npm ci --omit=dev12.8MB
  3. COPY package.json package-lock.json ./53.2kB
  4. COPY . .36.9kB
  5. WORKDIR /app8.19kB
  6. FROM node:24-alpine181MB

Predict

Now the order is good. You add a package, so package.json changes. What bakes again?

Pick one answer.

Try it

This recipe is in good order. Its layers sit in the build cache: Layers kept from the last bake. A step that did not change is reused, not baked again.. Change the code, build api:1.1, and count the CACHED lines.

Your laptop~/api

  • No open hatches

Lunchboxes (containers)

  • No containers yet

Frozen packs (images)

  • api:1.08 layers · 244MB
  • node:24-alpine4 layers · 244MB

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

Check

Good cache habit? Swipe right for yes, left for “needs work”.

Swipe right for good, left for needs work. Or use the buttons.

1 / 4

Copy the package files and install before copying the code

Copy the package files and install before copying the code

You did it!

You can now order a recipe so rebuilds stay fast.

Go deeper (optional)

docker history api:1.1 lists the layers, newest on top, with their sizes. Lines like ENV and CMD show 0B: notes, not layers. Deleting a file in a later layer only hides it. The image does not shrink.

Real mission

  1. docker history api:1.1

0 of 3 steps done · Your ticks are saved.