SuperAPI AI Directory

docker-syntax-dockerfile

Deployment & operations

View repository

Updated 10-15 22:17

About this skill

docker-syntax-dockerfile

Quick Reference

Parser Directives

Parser directives MUST appear at the very top of the Dockerfile, before any instructions, blank lines, or comments.

Directive Purpose Example
# syntax=docker/dockerfile:1 Enable BuildKit features (heredocs, mounts, etc.) ALWAYS include this
`# escape=`` Change escape character (useful on Windows) Optional
# check=error=true Enable build-time lint checks (v1.8.0+) Optional

ALWAYS start every Dockerfile with # syntax=docker/dockerfile:1 to enable BuildKit extensions.

All 17 Instructions at a Glance

Instruction Purpose Creates Layer?
FROM Set base image, start build stage Yes (base)
RUN Execute command during build Yes
CMD Default container command (overridable) No (metadata)
ENTRYPOINT Container executable (persistent) No (metadata)
COPY Copy files from context or stage Yes
ADD Copy with URL download and tar extraction Yes
ENV Set persistent environment variable Yes
ARG Set build-time variable (not persisted) No
WORKDIR Set working directory Yes
EXPOSE Document container port No (metadata)
VOLUME Declare mount point No (metadata)
USER Set user for subsequent instructions No (metadata)
HEALTHCHECK Define container health test No (metadata)
LABEL Add image metadata Yes
SHELL Override default shell No (metadata)
STOPSIGNAL Set container stop signal No (metadata)
ONBUILD Deferred instruction for child images No (metadata)

Critical Warnings

NEVER use latest tag in FROM -- ALWAYS pin to a specific version (node:20.11-bookworm-slim) or digest for reproducibility.

NEVER store secrets in ENV or ARG -- they are visible in docker history. ALWAYS use RUN --mount=type=secret instead.

NEVER use ADD when COPY suffices -- ADD has implicit behaviors (auto-extraction, URL download) that make builds less predictable.

NEVER use shell form for ENTRYPOINT -- the application will NOT be PID 1 and will NOT receive signals for graceful shutdown.

NEVER separate apt-get update and apt-get install into different RUN instructions -- the update layer gets cached and becomes stale.

ALWAYS combine related RUN commands with && to minimize layers.

ALWAYS clean up package manager caches in the same RUN layer as the install.


Shell Form vs Exec Form

Three instructions support both forms: RUN, CMD, ENTRYPOINT.

Form Syntax Shell Processing Variable Expansion Signal Handling
Shell CMD command arg1 Yes (/bin/sh -c) Yes ($VAR works) App is NOT PID 1
Exec CMD ["command", "arg1"] No (direct exec) No (use ENV for vars) App IS PID 1

ALWAYS use exec form for CMD and ENTRYPOINT in production images.

Use shell form for RUN when you need variable expansion, pipes, or command chaining.


CMD vs ENTRYPOINT Interaction Matrix

No ENTRYPOINT ENTRYPOINT (shell form) ENTRYPOINT (exec form)
No CMD Error -- no command /bin/sh -c entrypoint_cmd entrypoint_cmd
CMD (exec form) cmd_executable args /bin/sh -c entrypoint_cmd (CMD ignored) entrypoint_cmd cmd_args
CMD (shell form) /bin/sh -c cmd_string /bin/sh -c entrypoint_cmd (CMD ignored) entrypoint_cmd /bin/sh -c cmd_string

Best practice pattern:

ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["default-command"]
  • ENTRYPOINT (exec form) sets the fixed executable.
  • CMD (exec form) provides default arguments, overridable via docker run.
  • Shell form ENTRYPOINT ALWAYS ignores CMD -- NEVER combine them.

COPY vs ADD Decision Guide

Use Case Instruction Why
Copy local files COPY Explicit, predictable, no side effects
Copy from build stage COPY --from Only option for multi-stage copies
Download remote file with checksum ADD --checksum Integrity verification built in
Clone a Git repository ADD (Git URL) Supports branch/tag/commit references
Extract a local tar archive ADD Auto-extracts tar, tar.gz, tar.bz2, tar.xz
Everything else COPY ALWAYS prefer COPY by default

ALWAYS prefer COPY unless you specifically need ADD's extra features.


ENV vs ARG Comparison

Property ENV ARG
Available during build Yes Yes
Available at runtime Yes No
Visible in final image Yes (docker inspect) No
Visible in history Yes Yes (NEVER put secrets here)
Overridable docker run --env docker build --build-arg
Scope Current + subsequent stages Current stage only
Creates layer Yes No
Survives FROM Yes (inherited) No (must re-declare)

ALWAYS use ARG for build-time-only values (version numbers, build flags). ALWAYS use ENV for values needed at container runtime (PATH, config).


HEALTHCHECK Syntax

HEALTHCHECK [OPTIONS] CMD <command>
HEALTHCHECK NONE
Option Default Description
--interval=DURATION 30s Time between checks
--timeout=DURATION 30s Max time for single check
--start-period=DURATION 0s Grace period on startup
--retries=N 3 Consecutive failures before unhealthy

Exit codes: 0 = healthy, 1 = unhealthy, 2 = reserved (NEVER use).

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1

ALWAYS set --start-period for applications with slow startup.


ONBUILD Triggers

ONBUILD ADD . /app/src
ONBUILD RUN /app/src/compile.sh
  • NOT executed in the current build -- fires in child images using FROM <this-image>.
  • Useful for language-stack base images.
  • ONBUILD ONBUILD is NOT allowed (no chaining).
  • ONBUILD FROM and ONBUILD MAINTAINER are NOT allowed.

RUN Mount Types (BuildKit)

Mount Type Purpose Key Flags
--mount=type=cache Persist package manager caches target, sharing, id
--mount=type=bind Mount context without COPY layer target, from, source
--mount=type=secret Access secrets without baking in id, target, env
--mount=type=ssh Forward SSH agent id
--mount=type=tmpfs Temporary filesystem target

See references/instructions.md for complete mount syntax and examples.


Variable Substitution

Supported in: ADD, COPY, ENV, EXPOSE, FROM, LABEL, STOPSIGNAL, USER, VOLUME, WORKDIR, ONBUILD.

NOT supported in: RUN exec form, CMD exec form, ENTRYPOINT exec form (use shell form or ENV).

Modifier Example Result
Default value ${VAR:-default} Use default if VAR unset
Alternate value ${VAR:+alternate} Use alternate if VAR is set
Remove prefix ${VAR#pattern} Remove shortest prefix match
Remove suffix ${VAR%pattern} Remove shortest suffix match

Reference Links

Official Sources