Essential Dockerfile Instructions
LEVEL 0
The Problem
You know Dockerfiles have instructions, but there are many. Which ones do you actually need? What does each one do?
LEVEL 1
The Concept — The Essential Cooking Verbs
The Concept
In cooking, you need to know fundamental verbs: chop, mix, heat, season, serve.
In Dockerfiles, the essential “verbs” are:
- FROM — “Start with…”
- WORKDIR — “Work in this area…”
- COPY/ADD — “Add these ingredients…”
- RUN — “Do this preparation…”
- ENV — “Set the temperature to…”
- EXPOSE — “This will be served on…”
- CMD/ENTRYPOINT — “Serve by…”
Master these, and you can build almost any image.
LEVEL 2
The Mechanics — Each Instruction Explained
The Mechanics
FROM — The Foundation
FROM python:3.11-slim
FROM ubuntu:22.04
FROM node:18-alpine
FROM scratch # Empty image, for advanced use
Every Dockerfile starts here. It sets the base image you’re building upon.
WORKDIR — Set the Stage
WORKDIR /app
Sets the working directory for subsequent instructions. Like cd, but creates the directory if it doesn’t exist.
COPY — Bring in Files
COPY requirements.txt .
COPY src/ /app/src/
COPY --chown=user:group file.txt /app/
Copies files from the build context into the image.
ADD — Copy with Extras
ADD archive.tar.gz /app/ # Auto-extracts!
ADD https://example.com/file.txt /app/ # Downloads URLs
Like COPY, but can extract archives and fetch URLs. Prefer COPY unless you need these features.
RUN — Execute Commands
# Shell form
RUN apt-get update && apt-get install -y curl
# Exec form
RUN ["pip", "install", "flask"]
Runs commands during build. The result is saved in a new layer.
ENV — Set Environment Variables
ENV PORT=8080
ENV DATABASE_URL=postgres://localhost/db
Sets environment variables that persist into running containers.
ARG — Build-time Variables
ARG VERSION=1.0
RUN echo "Building version $VERSION"
Variables only available during build, not in running containers.
EXPOSE — Document Ports
EXPOSE 8080
EXPOSE 8080/tcp 8081/udp
Documents which ports the app uses. Doesn’t actually publish them — that’s done at runtime with -p.
CMD — Default Command
# Exec form (preferred)
CMD ["python", "app.py"]
# Shell form
CMD python app.py
The default command when no command is specified at docker run.
ENTRYPOINT — The Executable
ENTRYPOINT ["python"]
CMD ["app.py"] # default argument
Makes the container behave like an executable. CMD provides default arguments. docker run myapp script.py would run python script.py.
LEVEL 3
Combining Instructions
RUN Chaining
# Bad: 3 layers
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get clean
# Good: 1 layer
RUN apt-get update && \
apt-get install -y curl && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
COPY Order for Caching
# Good: Dependencies cached separately from code
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
# Bad: Any code change invalidates dependency cache
COPY . .
RUN pip install -r requirements.txt
LEVEL 4
Less Common but Useful
USER — Run as Non-Root
RUN useradd -m appuser
USER appuser
Security best practice: don’t run as root.
HEALTHCHECK — Container Health
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/health || exit 1
Tells Docker how to check if the container is healthy.
LABEL — Metadata
LABEL maintainer="dev@example.com"
LABEL version="1.0"
Add metadata to the image.