FROM and WORKDIR

FROM, WORKDIR and the Build Context

FROM names the base image and comes first (only ARG and parser directives may precede it). WORKDIR /app creates the directory and makes it the working directory for every later RUN, COPY and CMD, and for docker exec; prefer it to RUN cd, which lasts for one RUN only. The final . of docker build is the build context, the directory whose files COPY can see. The CLI sends it to BuildKit 10,294 , which may run on another machine, so nothing outside it, such as ../secrets, is reachable. Build from the project root:

Building BookNest's API imageShell
cd booknest
docker build -t l3-booknest-api:1.0 . 2>&1 | grep -E '^#[0-9]+ \[[0-9]|context:|naming'
docker image ls l3-booknest-api
Output
#6 transferring context: 368B done
#7 [1/5] FROM docker.io/library/node:24-slim@sha256:0e0ff40c39bc087845bfb27465a0df4ea419520094.
  ..
#8 [2/5] WORKDIR /app
#9 [3/5] COPY package.json package-lock.json ./
#10 [4/5] RUN npm ci --omit=dev && npm cache clean --force
#11 [5/5] COPY . .
#12 naming to docker.io/library/l3-booknest-api:1.0 done
IMAGE                 ID             DISK USAGE   CONTENT SIZE   EXTRA
l3-booknest-api:1.0   667f9a8162c1        339MB         82.1MB

BuildKit resolved node:24-slim to a digest and ran five steps; the image adds about 7 MB on disk to the base for Express 24,430 , pg and BookNest's source. -f selects a Dockerfile with another name, and --pull checks the registry for a newer base.