Docker Cheatsheet

Dockerfile

Use this Docker reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Instruction Reference

InstructionPurposeExample
FROMBase image (must be first)FROM node:22-alpine
RUNExecute command in a new layerRUN npm ci --omit=dev
CMDDefault command (overridable)CMD ["node", "server.js"]
ENTRYPOINTFixed executableENTRYPOINT ["python", "app.py"]
COPYCopy files from build contextCOPY package*.json ./
ADDLike COPY + auto-extract tarballs, URL fetchADD archive.tar.gz /data/
WORKDIRSet working directoryWORKDIR /app
ENVSet environment variableENV NODE_ENV=production
ARGBuild-time variableARG VERSION=1.0
EXPOSEDocument listening portEXPOSE 8080
VOLUMEDeclare a mount pointVOLUME ["/data"]
USERSwitch to user/UIDUSER node
LABELKey-value metadataLABEL version="1.0"
HEALTHCHECKContainer health probesee below
SHELLOverride default shellSHELL ["/bin/bash", "-o", "pipefail", "-c"]
STOPSIGNALSignal sent on docker stopSTOPSIGNAL SIGTERM
ONBUILDTrigger in child imagesONBUILD COPY . /app

Minimal Node.js Example

FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
USER node
CMD ["node", "server.js"]

Minimal Python Example

FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
USER nobody
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

CMD vs ENTRYPOINT

# CMD alone — all arguments overridable at runtime
CMD ["node", "server.js"]

# ENTRYPOINT alone — fixed binary, no default args
ENTRYPOINT ["python", "app.py"]

# Together (recommended) — ENTRYPOINT is the executable, CMD are default args
ENTRYPOINT ["nginx", "-g"]
CMD ["daemon off;"]
# docker run img               -> nginx -g "daemon off;"
# docker run img daemon on;    -> nginx -g "daemon on;"

Always use exec form (["cmd", "arg"]) for CMD/ENTRYPOINT so signals are delivered directly to the process, not a shell.

ARG and ENV

ARG NODE_VERSION=22          # build-time only; not available at runtime
ENV PORT=3000                # available at runtime too
ENV APP_HOME=/app \
    LOG_LEVEL=info

# Use ARG to parameterise the base image
ARG BASE=node:22-alpine
FROM ${BASE}
docker build --build-arg NODE_VERSION=20 .

HEALTHCHECK

HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD wget -qO- http://localhost:3000/health || exit 1

.dockerignore

node_modules
.git
.env*
dist
*.log
**/*.test.*

.dockerignore patterns follow .gitignore syntax. Always exclude node_modules, .git, and secrets before the first COPY . ..

Layer Caching Best Practices

# Copy dependency manifests FIRST so installs are cached
COPY package*.json ./
RUN npm ci

# Source changes only invalidate layers from here down
COPY . .

SHELL for Pipefail Safety

SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN curl -fsSL https://example.com | bash   # fails if curl fails

Labels (OCI standard)

LABEL org.opencontainers.image.source="https://github.com/org/repo" \
      org.opencontainers.image.version="1.2.3" \
      org.opencontainers.image.licenses="MIT"