What are the key Dockerfile instructions?
Quick Answer
FROM sets the base image. RUN executes a command at build time, creating a new layer. COPY/ADD bring files from the build context into the image. WORKDIR sets the working directory for later instructions. ENV sets persistent environment variables. EXPOSE documents which ports the container listens on — informational only, it doesn't actually publish them. USER sets which user later instructions and the container's process run as. CMD/ENTRYPOINT define what runs when a container starts.
Detailed Answer
A representative Dockerfile
FROM node:20-slim
WORKDIR /app
ENV NODE_ENV=production
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
USER node
CMD ["node", "server.js"]
Instruction by instruction
FROM— every Dockerfile starts with a base image. This sets the starting filesystem layers and OS/runtime foundation everything else builds on.RUN— executes a command at build time and commits its filesystem changes as a new layer. Used for installing packages, compiling code, or other build-time setup.COPY— copies files/directories from the build context (the directory you rundocker buildfrom) into the image's filesystem.WORKDIR— sets the working directory for all followingRUN,CMD,COPY, etc. Similar to runningcd, but it persists across instructions and creates the directory if it doesn't exist.ENV— sets an environment variable that persists into the running container, visible to the application at runtime. This is different fromARG, which only exists during the build.EXPOSE— purely documentation. It tells anyone reading the Dockerfile, and tools likedocker network, which ports the app listens on. It doesn't actually publish or open that port — you still need-pondocker runfor that.USER— sets which user later instructions run as, and which user the container's main process runs as by default. Important for not running as root.CMDandENTRYPOINT— both define what runs when a container starts, with an important behavioral difference between the two.
Additional instructions worth knowing
ARG BUILD_VERSION=dev # build-time-only variable (see the ARG vs ENV question)
LABEL maintainer="team@example.com" # arbitrary metadata attached to the image
VOLUME /data # documents/declares a mount point (see the storage topic)
HEALTHCHECK CMD curl -f http://localhost/health || exit 1 # see the container lifecycle topic
Why instruction order matters beyond just readability
Each instruction that touches the filesystem — RUN, COPY, ADD — creates a new cached layer. Docker's build cache invalidates from the first changed instruction onward, and every instruction after that must re-run, even if its own inputs didn't change. A Dockerfile is really executable documentation of how to build and run the application. That's why it deserves the same deliberate structure as any other piece of code, not just whatever order felt natural while developing.