Les bases de Docker Compose pour débutants en auto-hébergement
Tutoriels 14 février 2026 8 min read

Les bases de Docker Compose pour débutants en auto-hébergement

H

Hostly Team

Self-Hosting Enthusiast

Maîtrisez Docker Compose en 20 minutes. Apprenez à déployer, gérer et dépanner des applications auto-hébergées avec des exemples pratiques que vous utiliserez vraiment.

Chaque guide d'auto-hébergement dit « utilisez simplement Docker Compose » comme si c'était la chose la plus évidente du monde. Vous copiez un fichier docker-compose.yml, lancez docker compose up -d, et... priez pour que ça marche. Mais que se passe-t-il vraiment ? Comment réparer les choses quand elles cassent ? Comment personnaliser les configurations selon vos besoins ?

Qu'est-ce que Docker et pourquoi vous en soucier ?

Before Docker, installing software was a nightmare. Each application needed specific versions of dependencies, libraries, and runtimes — and they'd often conflict with each other. Installing application A might break application B.

Docker solves this by packaging applications in containers — self-contained environments with everything the application needs. Think of containers as lightweight virtual machines that:

  • Run in isolation — apps can't interfere with each other
  • Are reproducible — same container works identically everywhere
  • Start instantly — no boot time like traditional VMs
  • Share the host's kernel — extremely resource-efficient

Docker Compose extends this by letting you define and run multiple containers together. A typical self-hosted app might need:

  • The main application
  • A database (PostgreSQL, MySQL, MariaDB)
  • A cache (Redis, Memcached)
  • A reverse proxy (Caddy, Traefik, Nginx)

Docker Compose coordinates all of these with a single configuration file.

Installer Docker et Docker Compose

Let's get Docker installed. The official installation script works on most Linux distributions:

# Download and run the official install script
curl -fsSL https://get.docker.com | sh

# Add your user to the docker group (so you don't need sudo)
sudo usermod -aG docker $USER

# Log out and back in for group changes to take effect
exit

# After logging back in, verify installation
docker --version
# Docker version 25.x.x

docker compose version
# Docker Compose version v2.x.x

📝 Docker Compose v1 vs v2

The old docker-compose (with hyphen) is deprecated. Modern Docker uses docker compose (without hyphen) as a built-in plugin. All commands in this guide use the v2 syntax.

Anatomie d'un fichier docker-compose.yml

Let's decode a typical Docker Compose file piece by piece. Here's a simple example that runs a web app with a database:

services:
  webapp:
    image: nginx:latest
    container_name: my-webapp
    restart: unless-stopped
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
    environment:
      - TZ=America/New_York
    depends_on:
      - database
    networks:
      - app-network

  database:
    image: postgres:15
    container_name: my-database
    restart: unless-stopped
    environment:
      POSTGRES_USER: myapp
      POSTGRES_PASSWORD: secretpassword
      POSTGRES_DB: myapp_db
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - app-network

volumes:
  db-data:

networks:
  app-network:
    driver: bridge

Let's break down each section:

services:

The heart of the file. Each service becomes a container. Here we have two: webapp and database.

image:

Specifies which Docker image to use. Format is name:tag. Common tags:

  • latest — most recent version (can change unexpectedly)
  • stable — latest stable release
  • 15 or v2.1.0 — specific version (recommended for production)

container_name:

Optional. Gives your container a specific name instead of an auto-generated one. Makes logs and debugging easier.

restart:

Controls auto-restart behavior:

  • no — never restart (default)
  • always — always restart, even after reboot
  • unless-stopped — restart unless you manually stop it (recommended)
  • on-failure — only restart if it crashes

ports:

Maps ports between host and container. Format: "HOST:CONTAINER"

ports:
  - "8080:80"     # Host port 8080 → Container port 80
  - "127.0.0.1:8080:80"  # Only accessible from localhost

volumes:

Persists data outside the container. Two types:

volumes:
  # Bind mount: maps a host directory
  - ./html:/usr/share/nginx/html:ro   # :ro = read-only
  
  # Named volume: managed by Docker
  - db-data:/var/lib/postgresql/data

Named volumes survive container destruction. Bind mounts let you edit files directly.

environment:

Sets environment variables inside the container. Two syntax options:

environment:
  - VAR_NAME=value           # List format
  TZ: America/New_York       # Map format

depends_on:

Ensures containers start in order. The webapp won't start until database is running.

networks:

Puts containers on the same virtual network so they can communicate using container names as hostnames.

Commandes Docker Compose essentielles

Here are the commands you'll use daily:

# Start all services (detached mode)
docker compose up -d

# Stop all services
docker compose down

# Stop and remove volumes too (careful - deletes data!)
docker compose down -v

# View running containers
docker compose ps

# View logs
docker compose logs              # All services
docker compose logs webapp       # Specific service
docker compose logs -f           # Follow (stream) logs
docker compose logs --tail=100   # Last 100 lines

# Restart services
docker compose restart           # Restart all
docker compose restart webapp    # Restart specific service

# Rebuild and restart (after changing docker-compose.yml)
docker compose up -d --force-recreate

# Pull latest images
docker compose pull

# Execute command inside container
docker exec -it my-webapp bash   # Open shell
docker exec my-webapp ls /app    # Run single command

Exemple pratique : Déployer Uptime Kuma

Let's deploy a real application: Uptime Kuma, a self-hosted monitoring tool. This example demonstrates a complete, working setup.

# Create a directory
mkdir ~/uptime-kuma
cd ~/uptime-kuma

# Create docker-compose.yml
nano docker-compose.yml

Paste this configuration:

services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: unless-stopped
    ports:
      - "3001:3001"
    volumes:
      - ./data:/app/data
    environment:
      - TZ=Europe/Paris

Launch it:

docker compose up -d

# Check it's running
docker compose ps

# View logs
docker compose logs -f

Visit http://your-server-ip:3001 — you have a working monitoring tool!

Travailler avec les variables d'environnement

Hardcoding passwords in docker-compose.yml is bad practice. Use environment files instead:

# Create .env file (same directory as docker-compose.yml)
nano .env
DB_PASSWORD=super-secret-password
DB_USER=myapp
[email protected]

Reference these in your compose file:

services:
  database:
    image: postgres:15
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}

Docker Compose automatically loads .env from the same directory.

🔒 Security Tip

Add .env to .gitignore so you don't accidentally commit secrets to version control.

Le réseau expliqué

Understanding Docker networking prevents 90% of "why can't my app connect to the database?" problems.

Default Behavior

Without explicit network configuration, Docker Compose creates a default network. All services can reach each other using their service name as hostname:

# webapp can connect to database using:
postgres://database:5432/myapp_db
#         ^^^^^^^^ service name, not localhost!

Exposing Ports

Ports make services accessible from outside Docker:

ports:
  - "8080:80"           # Accessible from anywhere
  - "127.0.0.1:8080:80" # Only from host machine

If you're using a reverse proxy (Caddy, Traefik), you often don't need to expose ports at all — the proxy handles external traffic.

Custom Networks

For complex setups, create explicit networks:

services:
  frontend:
    networks:
      - frontend-net
      
  backend:
    networks:
      - frontend-net
      - backend-net
      
  database:
    networks:
      - backend-net  # Not accessible from frontend!

networks:
  frontend-net:
  backend-net:

Gérer les données avec les volumes

Containers are ephemeral — when they're removed, their internal data disappears. Volumes persist data:

Named Volumes (Recommended for databases)

services:
  database:
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:  # Docker manages this

View and manage volumes:

docker volume ls                    # List all volumes
docker volume inspect project_db-data  # Details
docker volume rm project_db-data       # Delete (careful!)

Bind Mounts (Good for config files)

volumes:
  - ./config:/app/config     # Relative path
  - /opt/data:/app/data      # Absolute path
  - ./config.yml:/app/config.yml:ro  # Single file, read-only

Déboguer les problèmes courants

Container Won't Start

# Check container status
docker compose ps

# View detailed logs
docker compose logs service-name

# Check for port conflicts
sudo lsof -i :8080

Container Keeps Restarting

# View exit code and recent logs
docker compose ps
docker compose logs --tail=50 service-name

# Common causes:
# - Missing environment variables
# - Database connection failures (check depends_on)
# - Permission issues on volumes

"Cannot connect to database"

  • Use the service name, not localhost: database:5432
  • Check if database is actually ready (not just started)
  • Verify network configuration

Permission Denied on Volumes

# Check the container's user
docker exec service-name id

# Fix ownership on host
sudo chown -R 1000:1000 ./data

Ajouter un reverse proxy

A reverse proxy lets you access multiple services through one domain with HTTPS. Caddy is the easiest option:

services:
  caddy:
    image: caddy:latest
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
      - caddy-config:/config
    networks:
      - proxy-net

  # Your apps connect to the same network
  webapp:
    image: your-app
    networks:
      - proxy-net
    # No ports needed! Caddy handles external access

volumes:
  caddy-data:
  caddy-config:

networks:
  proxy-net:

Caddyfile:

app.yourdomain.com {
    reverse_proxy webapp:8080
}

monitoring.yourdomain.com {
    reverse_proxy uptime-kuma:3001
}

Mettre à jour les applications

Keep your self-hosted apps updated for security:

# Pull latest images
docker compose pull

# Recreate containers with new images
docker compose up -d

# Remove old unused images
docker image prune -f

For major version upgrades, always check the application's release notes for breaking changes or required migrations.

Stratégie de sauvegarde

Back up your data regularly:

#!/bin/bash
# backup.sh - Run this as a cron job

BACKUP_DIR="/backup/$(date +%Y-%m-%d)"
mkdir -p "$BACKUP_DIR"

# Stop containers for consistent backup
cd /home/user/my-app
docker compose stop

# Backup bind mounts
tar -czf "$BACKUP_DIR/data.tar.gz" ./data ./config

# Backup named volumes
docker run --rm -v my-app_db-data:/source -v "$BACKUP_DIR":/backup alpine tar -czf /backup/db-data.tar.gz -C /source .

# Restart
docker compose up -d

Astuces utiles

Override for Development

Create docker-compose.override.yml for local changes that shouldn't be committed:

# docker-compose.override.yml
services:
  webapp:
    ports:
      - "8080:80"  # Expose directly for testing

Check Configuration Without Starting

docker compose config  # Validates and shows merged config

Run One-Off Commands

docker compose run --rm service-name command
# Example: run database migrations
docker compose run --rm webapp python manage.py migrate

Watch Resource Usage

docker stats  # Live resource monitoring

Aide-mémoire rapide

TaskCommand
Start servicesdocker compose up -d
Stop servicesdocker compose down
View logsdocker compose logs -f
List containersdocker compose ps
Restart servicedocker compose restart name
Update imagesdocker compose pull && docker compose up -d
Shell into containerdocker exec -it name bash
View configdocker compose config

Prochaines étapes

Now that you understand Docker Compose, you're ready to self-host anything. Here are some great starting points:

The self-hosting community is incredibly welcoming. When you get stuck, r/selfhosted is full of helpful people who've faced the same challenges.

You now have the foundation to deploy, debug, and maintain any self-hosted application. Welcome to the world of digital independence.