Quiz
Warm-up from unit 2: in `docker run -d -p 8080:80 --name web nginx`, what does `nginx` refer to?
The Dockerfile
So far you ran images other people built. To containerize your app, you write a Dockerfile: a plain text file, literally named Dockerfile, that lists the steps to assemble your image.
Here is a complete one for a small Python web app:
FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . EXPOSE 8000 CMD ["python", "server.py"]
Seven lines, and each one is a simple instruction: INSTRUCTION arguments. Docker executes them top to bottom to produce an image. Let's decode every line.
Line by line
FROM python:3.12-slim: every image starts from a base image. Instead of building an OS from scratch, you stand on one that already has Python 3.12. Note the pinned tag, as promised in lesson 2-1WORKDIR /app: cd into/appinside the image (creating it), so later instructions run thereCOPY requirements.txt .: copy a file from your project folder into the image's current directoryRUN pip install -r requirements.txt: execute a command during the build and save the result into the imageCOPY . .: now copy the rest of your source code inEXPOSE 8000: documentation that the app listens on port 8000. It does not publish the port,-pstill does that at run timeCMD ["python", "server.py"]: the default command a container runs when started. Exactly one per image, and it runs atdocker runtime, not build time
The same pattern in any language
The Dockerfile above is not Python-specific, it is a template. Here is the Node.js version of the exact same idea:
FROM node:22-slim WORKDIR /app COPY package.json package-lock.json ./ RUN npm install COPY . . EXPOSE 3000 CMD ["node", "server.js"]
Same skeleton, different base image and package manager: pinned slim base, dependency manifest copied first, dependencies installed, then the code. Once you can read one Dockerfile you can read almost all of them, because 90% of real Dockerfiles are this seven-line shape with the language swapped. (Why the manifest is copied before the code is the star of lesson 3-3.)
Building it
docker build -t myapp:v1 .
-t myapp:v1: tag the resulting image with a name and version, so you candocker run myapp:v1later.: the build context, the folder whose filesCOPYis allowed to see. The dot means the current directory
The workflow you now own end to end:
git clone <your project> docker build -t myapp:v1 . docker run -d -p 8080:8000 myapp:v1
Anyone with Docker can run those three commands on any machine and get an identical running app. That is the fix for lesson 1-1's broken server.
Quiz
What is the difference between RUN and CMD in a Dockerfile?
Problem
Which Dockerfile instruction must come first and picks the base image you build on top of?