FROM ubuntu:24.04★Start from an official base. Always pin a tag — never rely onlatestin production.FROM scratchEmpty base — for ultra-minimal images (Go static binaries, etc.).FROM node:22-alpine★Alpine-based images are ~5 MB — prefer for small production layers.FROM builder AS prod★Multi-stage: inherit from a named earlier stage, not an external image.
ENV PORT=8080★Persists into the running container; available at both build-time and runtime.ENV APP_HOME=/app \
NODE_ENV=productionMulti-var form — one layer for many variables.ARG VERSION=1.0★Build-time only — not visible in the final image. Override with--build-arg.ARG SECRETNo default — must be supplied; never use ARG for sensitive values (they leak inhistory).ENV SECRET=abc123avoidSecrets in ENV persist in the image. Use BuildKit--secretinstead.
WORKDIR /app★Sets the CWD for all subsequent RUN / COPY / CMD / ENTRYPOINT. Created automatically if missing.WORKDIR $APP_HOMEEnv vars are expanded — pair with ENV for DRY path definitions.USER appuser★Drop privileges before CMD/ENTRYPOINT. Never run production containers as root.USER 1001:1001UID:GID form — avoids relying on names that may not exist in the base.USER rootavoidRunning as root greatly expands the attack surface if the container is compromised.
RUN apt-get update && apt-get install \★
-y --no-install-recommends curlChain with&&— one layer, one cache entry. Always clean up in the same RUN.RUN --mount=type=cache --target=/root/.cache \
pip install -r requirements.txtBuildKit cache mount — keeps pip/apt caches across builds without baking them in.RUN --mount=type=secret,id=key \
cat /run/secrets/keyBuildKit secret mount — credential never stored in any layer.RUN ["executable", "param1"]Exec form — avoids shell string interpolation; use when you don't need a shell.RUN apt-get updateavoid
RUN apt-get install curlTwo separate RUNs create two layers; the first may be cached stale on the second build.
COPY src/ /app/src/★Copies host files into the image. Prefer COPY over ADD — intent is explicit.COPY --chown=appuser:appgroup . /app★Sets ownership in one step — avoids a separateRUN chownlayer.COPY --from=builder /app/dist /app/dist★Multi-stage: pull artifacts from a named previous stage.COPY --link package*.json /app/BuildKit linked copy — more cacheable, order-independent layer.ADD archive.tar.gz /app/Auto-extracts local tarballs. Only use ADD for this — otherwise prefer COPY.ADD https://example.com/file /app/avoidRemote URL in ADD is unpinned and uncached. UseRUN curl -fsSL …with a checksum instead.
EXPOSE 8080★Declares that the container listens on port 8080/tcp. Documentation only — does not publish.EXPOSE 8080/tcp 8081/udpExplicit protocol form. TCP is the default if omitted.
CMD ["node", "server.js"]★Default command — overridable bydocker run … <cmd>. Exec form recommended.CMD ["--port", "8080"]When combined with ENTRYPOINT, CMD supplies default arguments.ENTRYPOINT ["python", "app.py"]★Fixed executable — not overridable without--entrypoint. Use for tool containers.ENTRYPOINT ["/docker-entrypoint.sh"]Init script pattern — handles setup, thenexec "$@"to pass CMD through.CMD node server.jsavoidShell form wraps command in/bin/sh -c; SIGTERM goes to the shell, not node — graceful shutdown breaks.
VOLUME ["/data"]Declares a mount point. Docker creates an anonymous volume here atdocker runtime if no-vis given.VOLUME /var/log /var/dbMultiple paths in one instruction.RUN echo data > /data/fileavoid
VOLUME /dataWrites after VOLUME are discarded at build time — declare VOLUME last, write files before it.
SHELL ["/bin/bash", "-euo", "pipefail", "-c"]★Enables strict mode for all subsequent shell-form RUN/CMD/ENTRYPOINT instructions — catches typos, pipe failures.SHELL ["powershell", "-Command"]Windows containers — switch to PowerShell.
ONBUILD COPY . /appDeferred instruction — fires only when this image is used as a base (FROM) in a child build. Useful for base-image authors.STOPSIGNAL SIGQUITOverrides the signal sent to the container ondocker stop. Default is SIGTERM.
docker build -t name:tag .★Build with a tag, context = current directory.docker build -f path/Dockerfile .Explicit Dockerfile path — useful in mono-repos.docker build --no-cache -t name .Force a fresh build, ignoring all layer caches.docker build --build-arg VER=2.0 .★Override an ARG declared in the Dockerfile.docker build --target builder .★Stop at a named multi-stage target — e.g. to run tests in CI.docker build --platform linux/arm64 .Cross-compile for a different CPU architecture (requires BuildKit).DOCKER_BUILDKIT=1 docker build …Enable BuildKit explicitly (default in Docker ≥ 23).