It works on my laptop
Sam builds the orders service for an online shop. It runs perfectly on Sam's laptop.
On the server it crashes at once. The server has an older version of Python and is missing a library.
Teams lost whole days to this problem. This lesson shows the tool most teams now use to stop it.
By the end of this lesson
Note
I can explain what a container is and why teams use them.
Key words
| Word | What it means | Example |
|---|---|---|
| Dependency | something your app needs to run | Python 3.12, a library |
| Container | an app running with everything it needs, kept apart from the rest | |
| Image | the packed recipe a container starts from | |
| Dockerfile | a text file of steps that builds an image | |
| Registry | a shared store of images | |
| Virtual machine | a whole pretend computer with its own operating system |
The cells students fill in are left blank in this preview.
A container carries what the app needs
Every app has dependencies: the right version of Python, some libraries, some settings.
A container packs the app together with its dependencies. It runs kept apart from everything else on the machine.
So the app finds the same Python and the same libraries on every machine. The laptop and the server stop being different.
The same app in three places
| Where it runs | Python found | Library found | Result |
|---|---|---|---|
| Sam's laptop | 3.12 | Yes | Works |
| Server, no container | 3.8 | No | Crashes |
| Server, in a container | 3.12, from the image | Yes, from the image | Works |
The cells students fill in are left blank in this preview.
A common mistake
Warning
Many people think a container is a small virtual machine. It is not. A virtual machine runs a whole operating system of its own. A container shares the machine's operating system and packs only the app and its dependencies. That is why it starts in about a second.
An image is built from a Dockerfile
You do not pack a container by hand. You write a Dockerfile: a short list of steps.
A tool reads the steps in order and builds an image. The image is the packed result. Every container started from that image is the same.
Below, Bash writes a real Dockerfile and reads it back. Read each line, then make the change in the last comment.
Write and read a Dockerfile
mkdir -p orders-app && cd orders-app
printf 'print("Orders service is running")\n' > app.py
printf 'flask==3.0.3\n' > requirements.txt
cat > Dockerfile <<'EOF'
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app.py .
CMD ["python", "app.py"]
EOF
# Number every line of the recipe
cat -n Dockerfile
# Which base image does it start from?
grep FROM Dockerfile
# Change python:3.12-slim to python:3.11-slim above, then press Run again.
What each line does
| Line | What it does |
|---|---|
| FROM python:3.12-slim | Starts from an image that already holds Python 3.12 |
| WORKDIR /app | Works inside the folder /app |
| COPY requirements.txt . | Copies the list of libraries in |
| RUN pip install -r requirements.txt | Installs those libraries into the image |
| COPY app.py . | Copies the app's code in |
| CMD ["python", "app.py"] | Says what to run when a container starts |
The cells students fill in are left blank in this preview.
Why teams use containers
The team builds the image once. It goes to a registry, a shared store of images.
The test server and the live server pull the same image. What passed the tests is exactly what customers use.
When the shop is busy, the team starts ten copies of the image instead of one. Each copy starts in seconds.
What real Docker commands print
| Command | What it prints | What it means |
|---|---|---|
| docker build -t orders:1.4 . | Successfully tagged orders:1.4 | The image is built and named orders, version 1.4 |
| docker push registry.example.com/orders:1.4 | 1.4: digest: sha256:9f2c... | The image is now in the registry |
| docker run -d orders:1.4 | 3b7e1c0a9d42 | A container started; that is its id |
| docker ps | 3b7e1c0a9d42 orders:1.4 Up 5 seconds | One container is running |
The cells students fill in are left blank in this preview.