A Dockerfile is a declarative text document containing sequential instructions used by the Docker daemon or BuildKit engine to automate container image builds.
Dockerfile is a declarative configuration file format used to automate the creation of Open Container Initiative (OCI) and Docker container images. It defines a sequenced list of instructions—such as selecting a base image, copying application assets, executing package installations, configuring environment variables, establishing non-root user privileges, and defining default startup processes. Build engines like the Docker Daemon, BuildKit, and Podman parse this document into an Abstract Syntax Tree (AST) to produce lightweight, reproducible, and immutable container layers.
Audit, lint, and format your container definitions using our free in-browser Dockerfile Linter, convert Compose setups to Kubernetes with the Docker Compose to Kubernetes Converter, or validate deployment manifests with the Kubernetes YAML Validator.
| Specification | Details |
|---|---|
| Standard Filename | Dockerfile, Dockerfile.<target>, or Containerfile (Podman/OCI) |
| Default Build Engine | BuildKit (DOCKER_BUILDKIT=1 or Docker v23+) |
| Grammar Structure | Keyword-driven (INSTRUCTION arguments), case-insensitive (conventionally UPPERCASE) |
| Layer Model | Union File System (OverlayFS) with read-only cached intermediate layers |
| Standard Linter | Hadolint (Haskell-based AST linter enforcing DL3000–DL4006 rules) |
| Security Standards | CIS Docker Benchmark, NIST SP 800-190, Non-Root execution (UID > 0) |
# syntax=docker/dockerfile:1
# Stage 1: Build & Compilation
FROM node:20.18-alpine AS builder
WORKDIR /app
# Optimize layer caching: copy dependency manifests first
COPY package*.json ./
RUN npm ci
# Copy application source and compile
COPY . .
RUN npm run build && npm prune --production
# Stage 2: Minimal Production Runtime
FROM node:20.18-alpine AS runner
WORKDIR /app
# Harden security: create an unprivileged system user
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
# Copy only production artifacts from builder stage
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
# Set non-root execution and environment
USER nextjs
ENV NODE_ENV=production
EXPOSE 3000
# Container liveness check
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:3000/api/health || exit 1
# Exec JSON array form for proper PID 1 signal forwarding
CMD ["node", "dist/server.js"]
| Directive | Purpose | Best Practice Recommendation |
|---|---|---|
FROM |
Declares the base image and begins a new build stage. | Pin specific version tags or SHA-256 digests (never use :latest). |
WORKDIR |
Sets the current working directory for subsequent instructions. | Always use explicit, absolute paths (e.g., WORKDIR /app). |
COPY |
Copies files or directories from host or earlier build stages. | Prefer COPY over ADD; copy package manifests before source code for optimal caching. |
ADD |
Copies files, unpacks tarballs, or fetches remote URLs. | Avoid for regular files; use only when tarball auto-extraction is explicitly required. |
RUN |
Executes commands inside a new container filesystem layer. | Chain commands with && and clean package manager caches in the same instruction layer. |
ENV |
Sets persistent environment variables available at runtime. | Never store hardcoded passwords, tokens, or private keys in ENV instructions. |
ARG |
Defines build-time variables passed during docker build --build-arg. |
Keep sensitive build secrets out of ARG (use BuildKit --mount=type=secret). |
USER |
Configures the UID/GID for all subsequent operations. | Always drop root privileges by specifying a non-root user in production runtime stages. |
EXPOSE |
Documents the network ports the container intends to listen on. | Use as informational metadata; pair with orchestrator port mappings. |
HEALTHCHECK |
Defines a health probe command to verify application status. | Configure reasonable interval, timeout, and retry parameters to prevent false restarts. |
ENTRYPOINT |
Configures the primary executable process for the container. | Use JSON exec array form (["executable", "arg1"]) to ensure signal propagation. |
CMD |
Provides default arguments or fallback execution command. | Use JSON exec array syntax; combine with ENTRYPOINT for CLI utilities. |
| Rule ID | Severity | Description & Remediation |
|---|---|---|
| DL3000 | Error | Use absolute WORKDIR: Relative paths create non-deterministic directory hierarchies. |
| DL3002 | Warning | Last USER should not be root: Running as root (UID 0) expands container breakout impact. |
| DL3006 | Warning | Always tag the version of an image: Avoid untagged image references (e.g., FROM python). |
| DL3007 | Warning | Using latest is prone to errors: The mutable :latest tag breaks build reproducibility. |
| DL3008 | Warning | Pin versions in apt-get install: Pin exact package versions to guarantee deterministic builds. |
| DL3009 | Info | Delete the apt-get lists after installing: Remove /var/lib/apt/lists/* to reduce image size. |
| DL3013 | Warning | Pin versions in pip: Always pin Python dependency versions or install from requirements.txt. |
| DL3018 | Warning | Pin versions in apk add: Specify package versions or use apk add --no-cache. |
| DL3020 | Error | Use COPY instead of ADD for files and folders: ADD introduces ambiguous archive extraction. |
| DL3025 | Style | Use arguments JSON notation for CMD and ENTRYPOINT: Shell form blocks POSIX termination signals. |
| SC1000 | Security | Hardcoded secret in ENV: Secrets in environment directives remain visible in image metadata history. |
| OP1002 | Optimization | COPY . . before dependency installation: Invalidates build cache on every minor source change. |
# Build an image with a specific tag
docker build -t myapp:1.0.0 .
# Build with BuildKit and plain output for detailed layer timing
DOCKER_BUILDKIT=1 docker build --progress=plain -t myapp:1.0.0 .
# Inspect the layer history and storage contribution of an image
docker history myapp:1.0.0
# Run a container with non-root security options and health monitoring
docker run -d --name app-instance -p 3000:3000 --read-only myapp:1.0.0
# Scan image for known Common Vulnerabilities and Exposures (CVEs)
docker scout cves myapp:1.0.0
When using shell form (such as CMD node index.js), Docker runs your application inside a subshell process (/bin/sh -c "node index.js"). The shell process receives PID 1 inside the container, but standard Unix shells do not forward POSIX signals like SIGTERM or SIGINT to child processes. Consequently, orchestrators like Kubernetes cannot execute graceful shutdown routines, causing request drops until a forceful SIGKILL is issued after the timeout. Using JSON exec array form (CMD ["node", "index.js"]) ensures your application runs directly as PID 1 and receives termination signals immediately.
Multi-stage builds allow developers to define distinct compilation and runtime stages within a single Dockerfile. By compiling source code and installing build toolchains (compilers, headers, development SDKs) in an initial stage and copying only the resulting binary or minified bundle into a minimal runtime base (such as Alpine Linux or Google Distroless), you eliminate megabytes of unnecessary build tooling from the final production artifact while dramatically shrinking the container attack surface.
You can paste any Dockerfile into our free Dockerfile Linter to instantly check for Hadolint rule violations, exposed credentials, inefficient cache ordering, and missing health checks with line-by-line diagnostics and automated formatting.
Free, browser-based utilities to test, generate, and inspect Dockerfile (Container Image Build Specification) payloads directly.
Lint, validate, format, and optimize Dockerfiles with Hadolint-compatible rules, security checks, and multi-stage analysis.
Convert docker-compose.yml to Kubernetes Deployment, Service, ConfigMap, and PVC manifests.
Validate, lint, and format Kubernetes manifests against structure rules, deprecated APIs, and security best practices.
Validate, format and summarize GitHub Actions workflow YAML files against official schemas.
Parse, validate, and convert .env files between JSON, YAML, Docker, and Kubernetes formats.
Scan prompts, code, and text for prompt injection patterns, secret leaks, unsafe instructions, and PII exposure.