AI Hints
Home›Docker Tutorial›Build & Store
Docker · Lesson 4 of 8

Your First Dockerfile

Package your own app.

⏱ 2 min read▶ Video at 5:14🎓 Free
Watch this lesson in the Docker courseWatch on YouTube ↗Full Docker course

Running other people's images is useful, but the real power is packaging your own app. A Dockerfile is a plain text recipe: start from a base image, copy your code in, install dependencies, and say how to start the app. Let's containerise a tiny Python web app.

The app

app.pypython
from flask import Flask

app = Flask(__name__)

@app.get("/")
def home():
    return {"message": "Hello from a container!"}

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
requirements.txttext
flask==3.0.3
host="0.0.0.0" matters: inside a container, 127.0.0.1 would only be reachable from the container itself.

The Dockerfile

Each line is an instruction. Docker runs them top to bottom and saves each one as a layer, so unchanged steps are cached and rebuilds are fast. That is why we copy requirements.txt and install packages before copying the rest of the code.

Dockerfiledockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
InstructionMeaning
FROMthe base image to start from
WORKDIRthe folder inside the image to work in
COPYcopy files from your computer into the image
RUNrun a command while building
EXPOSEdocument the port the app listens on
CMDthe command that starts the container

Build and run

terminal
docker build -t hello-app .
[+] Building 12.4s (10/10) FINISHED
 => [1/5] FROM python:3.12-slim
 => [3/5] RUN pip install --no-cache-dir -r requirements.txt
 => naming to docker.io/library/hello-app
docker run -d --name hello -p 5000:5000 hello-app
a91c03f5be72...
curl localhost:5000
{"message":"Hello from a container!"}

Keep images small and builds fast

.dockerignoreexclude .git, venv and caches from the build
Slim base imagespython:3.12-slim instead of python:3.12
Order layersdependencies first, code last, for better caching
One process per containerrun the database in its own container
.dockerignoretext
.git
__pycache__/
.venv/
*.pyc

Check your understanding

Quick check
Why copy requirements.txt before the rest of the code?

Summary

Key takeaways
  • A Dockerfile is the recipe for an image
  • docker build -t NAME . builds it
  • Order instructions so layers cache well
Next up: Volumes: Keep Your Data — data that survives containers