World map

 

BM: Baca dalam Bahasa Melayu

World D2: Recipes

BuildKit cache mounts and build secrets

You will learn: to lend a key to one build step, and to keep downloads on a shelf between builds.

Checked with Docker Engine 29 on 31 Oct 2026

The problem

The token is passed with ARG. The build warns SecretsUsedInArgOrEnv. docker history then shows NPM_TOKEN=test-token-123 on two lines. Docker transcript: $ cat leak/Dockerfile FROM node:24-alpine ARG NPM_TOKEN WORKDIR /app COPY package.json package-lock.json .npmrc ./ RUN npm ci $ docker build --build-arg NPM_TOKEN=test-token-123 -t leaky:1.0 leak [+] Building 1.3s (9/9) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 141B 0.0s => WARN: SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NPM_TOKEN") (line 2) => [internal] load metadata for docker.io/library/node:24-alpine 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [1/4] FROM docker.io/library/node:24-alpine@sha256:8a32c8cf649a49915a6 0.0s => => resolve docker.io/library/node:24-alpine@sha256:8a32c8cf649a49915a6 0.0s => [2/4] WORKDIR /app 0.0s => [internal] load build context 0.0s => => transferring context: 440B 0.0s => [3/4] COPY package.json package-lock.json .npmrc ./ 0.0s => [4/4] RUN npm ci 1.2s => exporting to image 0.1s => => exporting layers 0.0s => => exporting manifest sha256:4c73b400576cc77a016e760ef3fcbce67b7d3bf3b 0.0s => => exporting config sha256:d000b0c253b132cb99495b392d60885a04b9966d8f5 0.0s => => exporting attestation manifest sha256:6a24dc7aad53822397d4f7f01c8b1 0.0s => => exporting manifest list sha256:42510cfdc9365bb60bc40b94ff193fee572b 0.0s => => naming to docker.io/library/leaky:1.0 0.0s => => unpacking to docker.io/library/leaky:1.0 0.0s 1 warning found (use docker --debug to expand): - SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "NPM_TOKEN") (line 2) $ docker history leaky:1.0 IMAGE CREATED CREATED BY SIZE COMMENT 42510cfdc936 3 seconds ago RUN |1 NPM_TOKEN=test-token-123 /bin/sh -c n… 12.3kB buildkit.dockerfile.v0 <missing> 3 seconds ago COPY package.json package-lock.json .npmrc .… 20.5kB buildkit.dockerfile.v0 <missing> 3 seconds ago WORKDIR /app 8.19kB buildkit.dockerfile.v0 <missing> 3 seconds ago ARG NPM_TOKEN=test-token-123 0B buildkit.dockerfile.v0 <missing> 2 days ago CMD ["node"] 0B buildkit.dockerfile.v0 <missing> 2 days ago ENTRYPOINT ["docker-entrypoint.sh"] 0B buildkit.dockerfile.v0 <missing> 2 days ago COPY docker-entrypoint.sh /usr/local/bin/ # … 20.5kB buildkit.dockerfile.v0 <missing> 2 days ago RUN /bin/sh -c apk add --no-cache --virtual … 5.48MB buildkit.dockerfile.v0 <missing> 2 days ago ENV YARN_VERSION=1.22.22 0B buildkit.dockerfile.v0 <missing> 2 days ago RUN /bin/sh -c addgroup -g 1000 node && … 167MB buildkit.dockerfile.v0 <missing> 2 days ago ENV NODE_VERSION=24.22.2 0B buildkit.dockerfile.v0 <missing> 9 days ago CMD ["/bin/sh"] 0B buildkit.dockerfile.v0 <missing> 9 days ago ADD alpine-minirootfs-3.24.3-x86_64.tar.gz /… 9.08MB buildkit.dockerfile.v0

Your laptop~/api

  • No open hatches

Lunchboxes (containers)

  • No containers yet

Frozen packs (images)

  • node:24-alpine4 layers · 244MB

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

You passed an npm token with ARG. The build even warned you: SecretsUsedInArgOrEnv. Now look at docker history: anyone with the image can read the token!

Watch

Tap the line that borrows the key.

0 of 1 found

A build secret: A key lent to one RUN step only. It never lands in a layer. is a key lent to one RUN step. When the step ends, the key goes back. No layer keeps it.

Try it

Build the safe recipe as api:1.0. Try it plain first and read the error. Then lend the key from token.txt.

Your laptop~/api

  • No open hatches

Lunchboxes (containers)

  • No containers yet

Frozen packs (images)

  • node:24-alpine4 layers · 244MB

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

Try it

Downloads are slow too. A cache mount: A pantry shelf BuildKit keeps between bakes, for downloads. It is not in the image. is a pantry shelf BuildKit keeps between builds. It is not in the image. Build the RUN line that uses it.

Tap the pieces in the right order.

…

Predict

You built api:1.0 with the secret. Will docker history api:1.0 show test-token-123?

Pick one answer.

Check

The build uses the secret mount. docker history lists RUN /bin/sh -c npm ci with no token anywhere. Docker transcript: $ docker build --secret id=npm_token,src=token.txt -t api:1.0 . [+] Building 1.3s (9/9) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 188B 0.0s => [internal] load metadata for docker.io/library/node:24-alpine 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 63B 0.0s => [stage-0 1/4] FROM docker.io/library/node:24-alpine@sha256:8a32c8cf649 0.0s => => resolve docker.io/library/node:24-alpine@sha256:8a32c8cf649a49915a6 0.0s => [stage-0 2/4] WORKDIR /app 0.0s => [internal] load build context 0.0s => => transferring context: 1.36kB 0.0s => [stage-0 3/4] COPY package.json package-lock.json .npmrc ./ 0.0s => [stage-0 4/4] RUN --mount=type=secret,id=npm_token,env=NPM_TOKEN,requi 1.2s => exporting to image 0.1s => => exporting layers 0.0s => => exporting manifest sha256:1e0b185043c5b0e3ec77a756772be38228be383a8 0.0s => => exporting config sha256:71735dabf55c103ca3da2416b3657a5985707beb3fe 0.0s => => exporting attestation manifest sha256:be6e365c920e71bb58732791f0f63 0.0s => => exporting manifest list sha256:a70ce11917463782f0673f37116c9d18467e 0.0s => => naming to docker.io/library/api:1.0 0.0s => => unpacking to docker.io/library/api:1.0 0.0s $ docker history --format "{{.CreatedBy}}" api:1.0 RUN /bin/sh -c npm ci # buildkit COPY package.json package-lock.json .npmrc .… WORKDIR /app CMD ["node"] ENTRYPOINT ["docker-entrypoint.sh"] COPY docker-entrypoint.sh /usr/local/bin/ # … RUN /bin/sh -c apk add --no-cache --virtual … ENV YARN_VERSION=1.22.22 RUN /bin/sh -c addgroup -g 1000 node && … ENV NODE_VERSION=24.22.2 CMD ["/bin/sh"] ADD alpine-minirootfs-3.24.3-x86_64.tar.gz /…

Your laptop~/api

  • No open hatches

Lunchboxes (containers)

  • No containers yet

Frozen packs (images)

  • node:24-alpine4 layers · 244MB

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

No token anywhere. The RUN layer only says npm ci. token.txt is in .dockerignore too, so it never reached the kitchen.

Check

Safe? Swipe right for yes, left for “needs work”.

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

1 / 5

Pass the npm token with --build-arg

Pass the npm token with --build-arg

You did it!

You can now lend secrets safely and keep downloads on a shelf.

Go deeper (optional)

Without env=, the secret is a file at /run/secrets/<id>. Leave out required=true, and a missing secret is simply not there. Secrets do not change the cache: a new token does not bake again. Use test tokens only while practising.

Real mission

  1. RUN --mount=type=secret,id=demo test -f /run/secrets/demo
  2. docker build --secret id=demo,src=token.txt -t demo:1.0 .

0 of 4 steps done · Your ticks are saved.