Skip to content

Dockerfile Reference ​

This is a comprehensive reference for all Dockerfile instructions. A Dockerfile is a text document containing instructions that Docker reads to build an image automatically.

Syntax Overview ​

dockerfile
# Comment
INSTRUCTION arguments
  • Instructions are case-insensitive but conventionally written in UPPERCASE.
  • Instructions are executed in order, top to bottom.
  • Each instruction creates a new image layer (with some exceptions).
  • The first instruction must be FROM (or ARG before FROM).

Parser Directives ​

Parser directives must appear at the very top of the Dockerfile, before any other instruction or comment:

dockerfile
# syntax=docker/dockerfile:1
# escape=\

FROM node:20-alpine
...
DirectiveDescriptionExample
syntaxSets the Dockerfile frontend (BuildKit)# syntax=docker/dockerfile:1
escapeSets the escape character# escape=\ (default) or # escape= ` ``

FROM ​

Sets the base image for the build stage.

dockerfile
# Basic usage
FROM ubuntu:22.04

# With alias for multi-stage builds
FROM node:20-alpine AS builder

# With platform specification
FROM --platform=linux/amd64 golang:1.22-alpine

# Using an ARG variable
ARG BASE_IMAGE=node:20-alpine
FROM ${BASE_IMAGE}

# Start from nothing (for statically compiled binaries)
FROM scratch

FROM Options ​

OptionDescriptionExample
--platformTarget platform--platform=linux/amd64
AS nameName the build stageAS builder

RUN ​

Executes a command during the image build process.

dockerfile
# Shell form (runs in /bin/sh -c)
RUN apt-get update && apt-get install -y curl

# Exec form (runs directly, no shell processing)
RUN ["apt-get", "install", "-y", "curl"]

# Multi-line with line continuation
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        curl \
        git \
        vim && \
    rm -rf /var/lib/apt/lists/*

# Heredoc syntax (BuildKit, Dockerfile 1.4+)
RUN <<EOF
apt-get update
apt-get install -y curl git
rm -rf /var/lib/apt/lists/*
EOF

# With mount options (BuildKit)
RUN --mount=type=cache,target=/root/.npm npm ci
RUN --mount=type=secret,id=token TOKEN=$(cat /run/secrets/token) && use-token
RUN --mount=type=ssh git clone git@github.com:user/repo.git
RUN --mount=type=bind,source=.,target=/src make -C /src build
RUN --mount=type=tmpfs,target=/tmp make build

RUN Mount Types ​

TypePurposePersistsIn Image
cacheCache package managers✅ Between builds❌
secretSensitive build data❌❌
sshSSH agent forwarding❌❌
bindHost files during buildN/A❌
tmpfsTemporary build storage❌❌

RUN --network ​

dockerfile
# Run with no network access (security)
RUN --network=none pip install --no-deps -r requirements.txt

# Run with default network
RUN --network=default curl -o file.tar.gz https://example.com/file.tar.gz

# Run on host network
RUN --network=host curl http://localhost:8080/api

CMD ​

Sets the default command that is executed when a container starts. There can be only one CMD instruction per Dockerfile (the last one takes effect).

dockerfile
# Exec form (preferred)
CMD ["node", "server.js"]
CMD ["python", "-u", "app.py"]

# Shell form
CMD node server.js

# As default parameters for ENTRYPOINT
ENTRYPOINT ["python"]
CMD ["app.py"]

# The CMD can be overridden at runtime:
# docker run my-image custom-command

CMD vs ENTRYPOINT Interaction ​

No ENTRYPOINTENTRYPOINT execENTRYPOINT shell
No CMDError/ep/bin/sh -c /ep
CMD exec/cmd p1/ep /cmd p1/bin/sh -c /ep
CMD shell/bin/sh -c /cmd/ep /bin/sh -c /cmd/bin/sh -c /ep

ENTRYPOINT ​

Configures the container to run as an executable. Unlike CMD, ENTRYPOINT is not easily overridden.

dockerfile
# Exec form (preferred)
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["postgres"]

# The container always runs docker-entrypoint.sh
# CMD provides default arguments
# docker run my-postgres           → docker-entrypoint.sh postgres
# docker run my-postgres bash      → docker-entrypoint.sh bash

# Shell form (cannot receive CMD arguments)
ENTRYPOINT exec java -jar app.jar
bash
# Override entrypoint at runtime
docker run --entrypoint /bin/sh my-image

COPY ​

Copies files and directories from the build context (or a build stage) into the image.

dockerfile
# Basic file copy
COPY package.json .
COPY package.json /app/

# Copy multiple files
COPY package.json package-lock.json ./

# Copy directory contents
COPY src/ /app/src/

# With wildcard patterns
COPY *.json /app/
COPY hom?.txt /app/

# With ownership
COPY --chown=user:group files/ /app/

# From another build stage
COPY --from=builder /app/dist /srv/public

# From an external image
COPY --from=nginx:latest /etc/nginx/nginx.conf /etc/nginx/

# With chmod (BuildKit)
COPY --chmod=755 scripts/ /app/scripts/

# With link (BuildKit — creates hard links for better cache)
COPY --link package.json /app/

COPY Options ​

OptionDescriptionExample
--fromCopy from a named stage or image--from=builder
--chownSet file ownership (Linux only)--chown=1000:1000
--chmodSet file permissions--chmod=755
--linkUse hard link for better caching--link
--parentsPreserve parent directories--parents
--excludeExclude files matching patterns--exclude=*.test.js

ADD ​

Similar to COPY but with extra features: tar extraction and URL support.

dockerfile
# Copy files (same as COPY)
ADD app.js /app/

# Auto-extract tar archives
ADD archive.tar.gz /app/

# Download from URL
ADD https://example.com/file.txt /app/

# With checksum verification
ADD --checksum=sha256:abc123... https://example.com/file.txt /app/

# With permissions
ADD --chown=user:group --chmod=755 app.tar.gz /app/

WARNING

Prefer COPY over ADD unless you specifically need tar extraction or URL download. COPY is more transparent and predictable.

ENV ​

Sets environment variables that persist in the built image and running containers.

dockerfile
# Key-value syntax
ENV NODE_ENV=production
ENV DB_HOST=localhost DB_PORT=5432

# Legacy syntax (single variable)
ENV NODE_ENV production

# Use in subsequent instructions
ENV APP_HOME=/app
WORKDIR $APP_HOME
bash
# Override at runtime
docker run -e NODE_ENV=development my-image

ARG ​

Defines build-time variables that are only available during the image build.

dockerfile
# Define with default value
ARG NODE_VERSION=20
ARG BUILD_DATE

# Use in FROM
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine

# ARG must be redeclared after FROM to be used in the stage
ARG APP_VERSION=1.0
RUN echo "Building version ${APP_VERSION}"
bash
# Override during build
docker build --build-arg NODE_VERSION=18 --build-arg BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) .

Predefined ARGs ​

ARGDescription
HTTP_PROXY / http_proxyHTTP proxy
HTTPS_PROXY / https_proxyHTTPS proxy
FTP_PROXY / ftp_proxyFTP proxy
NO_PROXY / no_proxyNo proxy list
BUILDKIT_INLINE_CACHEEnable inline cache
TARGETPLATFORMPlatform of the build target (e.g., linux/amd64)
TARGETOSOS of the target (e.g., linux)
TARGETARCHArchitecture of the target (e.g., amd64)
BUILDPLATFORMPlatform of the build host

WORKDIR ​

Sets the working directory for subsequent instructions.

dockerfile
# Absolute path
WORKDIR /app

# Relative path (relative to previous WORKDIR)
WORKDIR src
# Now in /app/src

# Using environment variables
ENV APP_HOME=/opt/myapp
WORKDIR $APP_HOME

EXPOSE ​

Documents the ports that the container listens on at runtime.

dockerfile
# Single port
EXPOSE 80

# Multiple ports
EXPOSE 80 443

# Specific protocol
EXPOSE 80/tcp
EXPOSE 53/udp

INFO

EXPOSE does not actually publish the port. Use -p flag at runtime to publish ports: docker run -p 8080:80 my-image.

VOLUME ​

Creates a mount point and marks it as holding externally mounted volumes.

dockerfile
# Single volume
VOLUME /data

# Multiple volumes
VOLUME ["/data", "/config"]

USER ​

Sets the user (and optionally group) for subsequent instructions and the running container.

dockerfile
# By name
USER appuser

# By UID
USER 1000

# By name with group
USER appuser:appgroup

# By UID:GID
USER 1000:1000

# Create user and switch
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

LABEL ​

Adds metadata to the image as key-value pairs.

dockerfile
LABEL maintainer="team@example.com"
LABEL version="1.0"
LABEL description="My application image"

# OCI standard labels
LABEL org.opencontainers.image.title="My App"
LABEL org.opencontainers.image.version="1.0.0"
LABEL org.opencontainers.image.description="Application description"
LABEL org.opencontainers.image.authors="team@example.com"
LABEL org.opencontainers.image.source="https://github.com/org/repo"
LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.created="2025-01-01T00:00:00Z"

HEALTHCHECK ​

Tells Docker how to test a container to check that it is still working.

dockerfile
# HTTP check
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
    CMD curl -f http://localhost:3000/health || exit 1

# TCP check
HEALTHCHECK CMD nc -z localhost 3000 || exit 1

# Custom script
HEALTHCHECK CMD /app/healthcheck.sh

# Disable health check (from base image)
HEALTHCHECK NONE
ParameterDefaultDescription
--interval30sTime between checks
--timeout30sCheck timeout
--start-period0sGrace period during startup
--start-interval5sInterval during start period
--retries3Failures before unhealthy

SHELL ​

Overrides the default shell used for shell-form commands.

dockerfile
# Default shell on Linux: ["/bin/sh", "-c"]
# Default shell on Windows: ["cmd", "/S", "/C"]

# Change to bash
SHELL ["/bin/bash", "-c"]
RUN echo "Using bash now"

# Change to PowerShell (Windows)
SHELL ["powershell", "-command"]
RUN Write-Output "Using PowerShell"

STOPSIGNAL ​

Sets the system call signal that will be sent to the container to stop it.

dockerfile
# Default is SIGTERM
STOPSIGNAL SIGTERM

# Use SIGQUIT for graceful shutdown
STOPSIGNAL SIGQUIT

# Numeric signal
STOPSIGNAL 9

ONBUILD ​

Adds a trigger instruction that executes when the image is used as a base for another build.

dockerfile
# In base image Dockerfile
FROM node:20-alpine
ONBUILD COPY package.json /app/
ONBUILD RUN npm install
ONBUILD COPY . /app/
WORKDIR /app

# When someone builds FROM this image:
# FROM my-base-image
# (ONBUILD instructions execute automatically)

Complete Production Dockerfile ​

dockerfile
# syntax=docker/dockerfile:1

# ==================================================
# Build Stage
# ==================================================
FROM node:20-alpine AS builder

ARG APP_VERSION=0.0.0

WORKDIR /app

COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci

COPY . .
RUN npm run build

# ==================================================
# Production Stage
# ==================================================
FROM node:20-alpine

LABEL org.opencontainers.image.title="My Application"
LABEL org.opencontainers.image.version="${APP_VERSION}"
LABEL org.opencontainers.image.source="https://github.com/org/repo"

RUN addgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR /app

COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/package.json ./
COPY --from=builder --chown=appuser:appgroup /app/package-lock.json ./

RUN --mount=type=cache,target=/root/.npm \
    npm ci --only=production && \
    npm cache clean --force

ENV NODE_ENV=production
ENV PORT=3000

USER appuser

HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
    CMD wget -q --spider http://localhost:${PORT}/health || exit 1

EXPOSE ${PORT}

CMD ["node", "dist/server.js"]

Next Steps ​

基于 MIT 许可发布