“It works on my machine”: the phrase every developer has heard. The application works locally, but in production the Node version, a system library, or an environment variable differs. Docker solves this problem by packaging the application with its whole environment in an image that runs the same way everywhere.
The vocabulary
- Image: a read-only template (file system + metadata), built in successive layers. Example:
node:22-slim. - Container: a running instance of an image, with its own writable layer. You can run ten containers from the same image.
- Registry: a repository of images (Docker Hub, GitHub Container Registry, cloud registries).
Unlike a virtual machine, a container does not include a complete operating system: it shares the host’s kernel and isolates itself using Linux namespaces and cgroups. It starts in a fraction of a second and weighs a few tens of MB.
A container’s lifecycle
# Download an image from Docker Hub
docker pull nginx:1.27-alpine
# Run a container in the background (-d), named, host port 8080 -> container port 80
docker run -d --name web -p 8080:80 nginx:1.27-alpine
# http://localhost:8080 shows the nginx welcome page
docker ps # running containers (-a to include stopped ones)
docker logs -f web # follow the logs (the process's standard output)
docker exec -it web sh # open a shell INSIDE the container
docker stop web # stop gracefully (SIGTERM signal then SIGKILL)
docker rm web # remove the container
docker images # images present locally
A container lives as long as its main process. If that process ends, the container stops.
Publishing ports
By default, a container is isolated from the host’s network. The -p HOST:CONTAINER option publishes a port: -p 3000:3000 makes a Node API reachable on localhost:3000. To expose it only locally: -p 127.0.0.1:3000:3000.
Persisting data
Everything written inside the container is lost when it is removed. For a database, use a volume:
docker volume create pgdata
docker run -d --name db \
-e POSTGRES_PASSWORD=dev_seulement \
-v pgdata:/var/lib/postgresql/data \
-p 127.0.0.1:5432:5432 \
postgres:17
-esets an environment variable;-v pgdata:/pathmounts the named volume: you can delete and recreate the container without losing the data.
In development, you also mount a host folder (bind mount): -v "$PWD":/app.
Cleaning up
docker system df # space used
docker container prune # removes stopped containers
docker image prune # removes untagged images
Key takeaways
Image = template, container = instance. docker run with -d, -p, -e, -v, and --name covers most uses; ps, logs, and exec are for diagnosis.
Exercises
Solutions and tests stay on the server. In the student space, your code is run and checked, and the tutor gives hints before the solution.
Run and inspect a web server
Run an
nginx:1.27-alpinecontainer namedvitrine, in the background, reachable on port 8080 of your machine. Check that it responds, look at its logs, open a shell in it to list/usr/share/nginx/html, then stop it and remove it.- `docker ps` shows the `vitrine` container with `0.0.0.0:8080->80/tcp`
- `curl -I http://localhost:8080` returns `HTTP/1.1 200 OK`
- `docker logs vitrine` shows the GET request made by curl
- `docker exec vitrine ls /usr/share/nginx/html` lists `index.html`
- After `docker stop vitrine && docker rm vitrine`, `docker ps -a` no longer shows it
Persist data with a volume
Create a volume
notes. Run analpine:3.20container that writes the date to/data/journal.txt, mounting this volume on/data, then remove the container. Run a second container with the same volume and display the file.- `docker volume ls` lists the `notes` volume
- The first container is run with `-v notes:/data` and the `--rm` option
- The second container displays the contents of `/data/journal.txt` with `cat`
- The date written by the first container is indeed present
Image or container?
You run
docker run -d nginx:1.27-alpinethree times. How many images and containers do you have?- 3 images and 3 containers
- 1 image and 3 containers
- 1 image and 1 container
- 3 images and 1 container
End-of-lesson quiz
What does a container share with the host machine?
- Nothing, it brings its own kernel
- The operating system kernel
- Its database
What does
-p 8080:3000do?- Publishes container port 3000 on host port 8080
- Publishes container port 8080 on host port 3000
- Limits memory
Which command opens a shell in a running container?
- docker run -it name sh
- docker exec -it name sh
- docker logs name
The rest of the course
- Writing a Dockerfile for Your Application18 min
- Optimizing and Securing Your Images18 min
- Docker Compose: Orchestrating a Multi-Service Application18 min
- Deploying to Production: Registry, CI/CD, and HTTPS20 min