1. Containers and virtual machines #
Isolating without virtualizing an entire system.
The principle #
A container is a process isolated by namespaces (its own view of processes, network and files) and limited by cgroups (CPU, memory). It starts in a few seconds, weighs a few tens of MB and ensures that « it works on my machine » means « it works everywhere ».
| Criterion | Virtual machine | Container |
|---|---|---|
| Startup | Minutes | Seconds |
| Size | GB | MB |
| Isolation | Strong (hypervisor) | Process (shared kernel) |
| Density | Tens per host | Hundreds per host |
2. Docker's architecture #
Images, containers, registries.
The building blocks #
- Image: a read-only template, built from stacked layers.
- Container: a running instance of an image (with a writable layer).
- Registry: an image repository (Docker Hub, GHCR, private registry).
- Volume: persistent storage outside the container's life cycle.
docker version && docker info | head -20
docker run hello-world # télécharge et exécute une image de test
docker images && docker ps -a3. The essential commands #
A container's life cycle.
Running and managing #
docker run -d --name web -p 8080:80 -e TZ=Europe/Paris --restart unless-stopped nginx:1.27
docker run -it --rm alpine sh # shell jetable
docker ps / docker ps -a # conteneurs en cours / tous
docker logs -f --tail 50 web
docker exec -it web sh
docker stop web && docker start web && docker restart web
docker rm -f web # supprimer un conteneur
docker stats --no-stream # consommation CPU/mémoire
docker inspect web | jq '.[0].NetworkSettings.IPAddress'
docker cp web:/etc/nginx/nginx.conf ./nginx.conf
docker pull nginx:1.27 && docker images
docker image prune -a && docker system prune --volumes # nettoyer (attention !)
docker system df # espace utilisé4. Building your images and orchestrating locally #
Dockerfile, volumes, networks, Compose.
Dockerfile #
# Dockerfile (application Python)
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
USER 10001
EXPOSE 8000
HEALTHCHECK CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"
CMD ["gunicorn", "-b", "0.0.0.0:8000", "app:app"]docker build -t mon-app:1.0 .
docker run -d -p 8000:8000 mon-app:1.0
docker tag mon-app:1.0 registre.exemple.fr/equipe/mon-app:1.0 && docker push registre.exemple.fr/equipe/mon-app:1.0
docker history mon-app:1.0 # couches et taillesGood practice: Order instructions from least to most frequently changing (dependencies before code) to benefit from layer caching; use multi-stage builds for tiny final images.
Volumes, networks and Compose #
docker volume create pgdata
docker network create backend
docker run -d --name db --network backend -v pgdata:/var/lib/postgresql/data -e POSTGRES_PASSWORD=secret postgres:16
docker run -d --name api --network backend -p 8000:8000 -e DB_HOST=db mon-app:1.0 # "db" résolu par DNS# compose.yaml
services:
api:
build: .
ports: ["8000:8000"]
environment: { DB_HOST: db }
depends_on: { db: { condition: service_healthy } }
db:
image: postgres:16
environment: { POSTGRES_PASSWORD: secret }
volumes: [pgdata:/var/lib/postgresql/data]
healthcheck: { test: ["CMD-SHELL", "pg_isready -U postgres"], interval: 5s, retries: 10 }
volumes: { pgdata: {} }docker compose up -d --build
docker compose ps && docker compose logs -f api
docker compose down -v