Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Containers  ›  Capstone Project

Writing a Dockerfile

Docker 12 minA Dockerfile builds an image layer by layer, and ordering instructions from rarely to often changing keeps the build cache useful while .dockerignore and run-time configuration keep secrets out.

Writing a Dockerfile

Pulling other people's images is half the story. To ship notes-api itself you write a Dockerfile: a short recipe that turns your code into an image anyone can run. Written carelessly, every one-line change triggers a five-minute rebuild; written well, it rebuilds in seconds.

The rule

Order the Dockerfile from what changes rarely to what changes often.

Each instruction creates a layer, and Docker caches layers. On a rebuild it reuses every cached layer until it reaches the first instruction whose input changed; from there on, everything is rebuilt.

FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

USER nobody
EXPOSE 8000
CMD ["python", "-m", "notes_api"]
  • FROM picks the base image. A slim base keeps the image small.
  • WORKDIR sets the folder later instructions run in.
  • COPY requirements.txt then RUN pip install: dependencies change rarely, so this slow layer stays cached.
  • COPY . . brings in your code, which changes on almost every build, so it comes after the install.
  • USER nobody avoids running the app as root.
  • EXPOSE documents the port; CMD says what the container runs.

A .dockerignore file keeps things out of the build: .git, .venv, local logs and above all .env files with secrets. Secrets belong in environment variables or a secret store at run time, never baked into an image, where anyone who pulls it can read them.

docker build -t notes-api:1.1 .
docker run -d -p 8080:8000 notes-api:1.1

The shortcut

Read your Dockerfile top to bottom and ask of each line: "how often does this change?" The answers should go from "almost never" to "every commit". Any expensive step below a frequently changing COPY is a cache-buster.

Fixing a slow buildStep 1 of 4
  1. The slow version

    COPY . . sits first, then RUN pip install. Every code change invalidates the copy layer.

Drills

Answer fast — trust the rule.

quick drill

Why copy requirements.txt and install before copying the rest of the code?

quick drill

Which instruction sets the command a container runs when it starts?

quick drill

Where should a database password for the container come from?

quick drill

What does .dockerignore do?

Remember

  • Order the Dockerfile from what changes rarely to what changes often.
  • Shortcut: ask "how often does this change?" of each line, top to bottom.
  • Trap: COPY . . before installing dependencies, and baking secrets into images.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainReview a Dockerfile

A teammate's Dockerfile for notes-api is: FROM python:3.12, COPY . ., RUN pip install -r requirements.txt, CMD python -m notes_api. The repository also contains a .env file with the database password. Explain what you would change and why.