Dockerfile Instructions Reference

All Dockerfile instructions with syntax, effect on layers and best-practice notes.

Searchable reference for every Dockerfile instruction — FROM, RUN, COPY, ADD, ENV, ARG, EXPOSE, CMD, ENTRYPOINT, HEALTHCHECK and more — with syntax, whether each creates an image layer, and practical best-practice notes. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

Which Dockerfile instructions create a new image layer?

RUN, COPY and ADD each commit a new filesystem layer. FROM starts a stage without adding a layer, and metadata instructions like ENV, CMD, ENTRYPOINT, LABEL and EXPOSE change image configuration without creating a filesystem layer.

Dockerfile instructions at a glance

A Dockerfile is an ordered list of instructions that the Docker builder turns into an image. This reference lists every instruction with its exact syntax, whether it creates a new filesystem layer, and a best-practice note. Search the table to jump straight to the instruction you need.

How it works

Docker images are built as a stack of read-only layers. The builder reads your Dockerfile top to bottom and, for layer-creating instructions, runs the step inside a temporary container and commits the resulting filesystem diff as a new layer. Three instructions create layers — RUN, COPY and ADD — so the order and grouping of those lines directly controls image size and cache reuse.

Other instructions only change image configuration (metadata) rather than the filesystem: ENV, ARG, CMD, ENTRYPOINT, EXPOSE, LABEL, WORKDIR, USER, VOLUME, HEALTHCHECK, STOPSIGNAL, SHELL and ONBUILD. FROM is special — it begins a build stage by selecting a base image without adding a layer of its own.

Each instruction is also a cache key. If nothing above a line changed, Docker reuses the cached layer. That is why you copy and install dependencies before copying application source: dependency layers stay cached across code edits.

Tips and examples

  • Combine related shell steps in a single RUN with && and clean package caches in the same line so the cleanup lands in the same layer:
RUN apt-get update \
 && apt-get install -y --no-install-recommends curl \
 && rm -rf /var/lib/apt/lists/*
  • Pair ENTRYPOINT with CMD for a sensible default that callers can override:
ENTRYPOINT ["python", "app.py"]
CMD ["--port", "8080"]
  • Use multi-stage builds and COPY --from=builder to ship only compiled artifacts, keeping the runtime image small.
  • Run as a non-root USER, add a HEALTHCHECK, and label images with the org.opencontainers.image.* convention for traceability.

Instruction-by-instruction notes for the most misunderstood cases

FROM and multi-stage builds. A Dockerfile may contain multiple FROM lines. Each one begins a new build stage. Stages are named with AS <name> and can be referenced in later COPY --from=<name> instructions. The final FROM determines the base of the image that gets tagged and pushed — intermediate stages exist only during the build.

ARG vs ENV. Both set variables, but they behave differently. ARG is available only during the build (not at container runtime) and can be overridden with --build-arg. ENV is baked into the image and available at runtime too. Use ARG for build-time configuration like a version number; use ENV for things the running application needs. Neither should ever hold credentials — they appear in docker history.

COPY vs ADD. Prefer COPY for almost everything. ADD has two extra behaviours: it can unpack local tar archives and it can fetch remote URLs. Both features are footguns — remote fetching skips the build cache and bypasses checksum verification. Reserve ADD only for the tar-extraction use case when you specifically need it.

CMD vs ENTRYPOINT. Use the exec form (JSON array) for both to avoid shell wrapping issues with signal handling:

ENTRYPOINT ["node", "server.js"]
CMD ["--port", "3000"]

With this pattern, docker run myimage --port 4000 replaces only the CMD arguments. docker run --entrypoint /bin/sh myimage overrides the entrypoint entirely, which is how you get a debugging shell in a production image.

VOLUME. Declaring a VOLUME in the Dockerfile creates an anonymous volume at that path at container start. It guarantees the path is a mount point but does not determine where data is stored — that is the host’s or orchestrator’s decision. For explicit, named volume mounts, omit VOLUME from the Dockerfile and manage mounts in compose.yaml or the docker run -v flag instead.

ONBUILD. Instructions prefixed with ONBUILD are deferred and run only when the image is used as a base in another Dockerfile’s FROM. This is useful for base images (a common pattern in CI/CD frameworks), but it makes behaviour non-obvious to readers of the child Dockerfile and is rarely the right choice for application images.