DanLevy.net

Conseils essentiels de sécurité Docker pour l'auto‑hébergement

Sécurisez vos services auto‑hébergés, de la défense à la surveillance !

Table of Contents

🧗‍♀️ Pour les courageux

Si vous auto‑hébergez des services Docker, la sécurité repose entièrement sur vous — aucun fournisseur de cloud ne vous protégera des scans de ports ou d’une configuration bâclée. Que vous déployiez des applications sur votre réseau domestique ou que vous louiez des VPS chez des fournisseurs comme Vultr, DigitalOcean, Linode, AWS, Azure ou Google Cloud, il vous faudra verrouiller le tout — et vérifier que vous l’avez fait correctement.

Dans ce guide, nous passerons en revue la sécurité Docker : des techniques « moins connues » aux pratiques « difficiles à bien faire »; nous explorerons les jetons canari, les volumes en lecture‑seule, les règles de pare‑feu, la segmentation et le renforcement du réseau, l’ajout de proxys authentifiés, et bien plus encore.

Nous comparerons également les réseaux domestiques aux environnements cloud publics et vous montrerons comment configurer un proxy d’authentification basique avec Nginx. À la fin, vous disposerez de plusieurs options pour tenir à distance les indésirables (amis, famille, et parfois même vous-même…).

Ça fait beaucoup de choses ! Mais la plupart sont interconnectées, et vous pouvez choisir ce qui correspond le mieux à votre infrastructure. 🍀

🔄 La danse du :latest

Maintenir les images à jour est essentiel pour la sécurité. Cependant, s’appuyer sur :latest peut introduire des changements incompatibles ou des builds vulnérables sans étape de révision.

La façon sûre de mettre à jour

Combinez les commandes de mise à jour avec pull ou build afin de rafraîchir délibérément les images, puis redémarrez pendant une fenêtre où vous pouvez détecter une régression.

update-and-run.sh
#!/bin/bash
docker compose pull && \
docker compose up -d

Épinglage de version vs latest

Choisir la bonne version à épingler est un exercice d’équilibre entre stabilité et sécurité. Voici quelques stratégies courantes :

docker-compose.yml
# ...
# Épinglage de version exacte, idéal pour les services critiques
image: postgres:17.2
# Épinglage de version de correctif, bon pour les services non critiques
image: postgres:17.2
# Épinglage de version majeure, parfait pour les projets de loisir
image: postgres:17
# Yolo, à éviter si possible
image: postgres:latest

Utilisez Dependabot ou Renovate pour ouvrir des PR d’updates révisables. Pour tout ce que vous seriez triste de reconstruire à 2 h du matin, épinglez à une version ou un digest spécifique et laissez l’automatisation vous indiquer quand migrer.

​Faites‑moi part de vos outils préférés pour garder les images Docker à jour !

🔐 Gestion des secrets

Il existe de nombreuses façons de gérer les secrets, mais l’une des règles les plus importantes à respecter est : ne jamais coder en dur des secrets dans vos images Docker ou les valider dans git. C’est l’une des erreurs de sécurité les plus fréquentes, cela crée un risque à long terme, et c’est pénible à corriger.

Stocker les secrets de manière sécurisée est un sujet conséquent avec de nombreuses options, des fichiers .env, Docker secrets, 1Password/Bitwarden, ou un gestionnaire de secrets comme HashiCorp Vault ou AWS Secrets Manager.

Vous devrez choisir le niveau « approprié » d’effort et de sécurité pour votre cas d’usage.

Générer des secrets forts

Voici un petit script pour générer de nouveaux secrets destinés à un fichier .env :

generate-secrets.sh
#!/bin/bash
generate_secret() {
local length=${1:-30}
local generate_length=$((length + 4))
openssl rand -base64 "$generate_length" | tr -d '+=/\n' | cut -c1-"$length"
}
[ -f .env ] && { echo ".env file already exists!"; exit 1; }
cat > .env << EOL
POSTGRES_PASSWORD=$(generate_secret)
JWT_SECRET=$(generate_secret 64)
SESSION_KEY=$(generate_secret 24)
REDIS_PASSWORD=$(generate_secret 20)
UNSAFE_PLACEHOLDER=__WARNING_REPLACE_RANDOM_TEXT__
EOL
echo "New .env file generated with secure random values!"

Jetons Canary

Canary Tokens sont un excellent moyen de détecter si vos secrets ont été compromis (et exploités). Ils fonctionnent comme un fil‑piège que l’on peut ajouter à n’importe quel fichier sensible, URL ou jeton.

Envisagez de les placer à côté des secrets qui vous inquiètent réellement : fichiers .env, variables CI, gestionnaires de mots de passe, dossiers de sauvegarde et identifiants cloud. Ne transformez pas cela en théâtre ; placez les fils‑pièges là où un véritable attaquant ou votre futur vous-même risquerait de les toucher.

Il existe de nombreux types de « jetons » canary, depuis les jetons AWS, les numéros de carte de crédit factices, les fichiers Excel et Word, les fichiers Kubeconfig, les identifiants VPN, jusqu’aux dumps SQL qui peuvent eux aussi contenir un fil‑piège !

Bonnes pratiques pour les jetons Canary

Passer de .env au trousseau de clés macOS

Pour les utilisateurs macOS, l’une des options les plus simples consiste à exploiter le trousseau de clés.

Voici une méthode basique pour automatiser le chargement des secrets depuis le trousseau macOS, compatible avec TouchID et légèrement plus sûre que les fichiers .env.

Original credit: Brian Hetfield and Jan Schaumann.

Commandes d’aidePersister les secrets dans l’environnementUtiliser les secrets par commande
keychain-secrets.sh
### Fonctions pour définir et récupérer des variables d’environnement depuis le trousseau macOS ###
### Adapté de : https://www.netmeister.org/blog/keychain-passwords.html et
Original credit: [Brian Hetfield](https://gist.github.com/bmhatfield/f613c10e360b4f27033761bbee4404fd) and [Jan Schaumann](https://www.netmeister.org/).
# Utilisation : get-keychain-secret VARIABLE_ENV
function get-keychain-secret () {
security find-generic-password -w -a ${USER} -D "environment variable" -s "${1}"
}
# Utilisation : set-keychain-secret VARIABLE_ENV
# Vous serez invité à saisir la valeur du secret !
function set-keychain-secret () {
[ -n "$1" ] || print "Missing environment variable name"
# demander le secret à l’utilisateur
echo -n "Enter secret for ${1}"
read secret
[ -n "$secret" ] || return 1
( [ -n "$1" ] || [ -n "$secret" ] ) || return 1
security add-generic-password -U -a ${USER} -D "environment variable" -s "${1}" -w "${secret}"
}
~/code/app/.env-secrets.sh
source ~/keychain-secrets.sh
# Charger les variables d’environnement dans le shell actuel
export AWS_ACCESS_KEY_ID=$(get-keychain-secret AWS_ACCESS_KEY_ID);
export AWS_SECRET_ACCESS_KEY=$(get-keychain-secret AWS_SECRET_ACCESS_KEY);
# Remarque : si un attaquant peut exécuter `env` dans votre shell, ces secrets pourraient être exposés !
~/code/app/scripts/env-run.sh
#!/usr/bin/env bash
source ~/keychain-secrets.sh
# Spécifier tous les secrets pour ce projet
AWS_ACCESS_KEY_ID=$(get-keychain-secret AWS_ACCESS_KEY_ID) \
AWS_SECRET_ACCESS_KEY=$(get-keychain-secret AWS_SECRET_ACCESS_KEY) \
"$@"
# Remarque : un wrapper shell aide à empêcher les secrets de rester
# dans l’environnement. Et il est sûr de le versionner.
# Utilisation :
# ./scripts/env-run.sh docker compose up -d
# ./scripts/env-run.sh docker run -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY ...

🌐 Risque réseau

Réseaux personnalisés & ports internes

Isoler correctement les services avec les réseaux Docker est un moyen crucial de réduire votre surface d’attaque.

Évitez de percer des trous dans votre réseau ! Un seul port mal configuré peut rapidement devenir catastrophique.

Par défaut, les services sur un LAN privé ne sont pas exposés à Internet — vous devez explicitement rediriger les ports depuis votre routeur.

Docker sur LAN

Que vous soyez développeur lançant des serveurs de dev en local, ou que vous auto‑hébergiez des services depuis votre réseau domestique, les suppositions sur le modèle réseau de Docker peuvent entraîner des problèmes.

Les développeurs sont souvent surpris de constater que les méthodes « traditionnelles » pour sécuriser les serveurs Linux (iptables, restrictions sysctl tcp/ip) peuvent échouer silencieusement sur des hôtes Docker ! Cela se produit surtout lorsqu’on auto‑héberge ou qu’on fonctionne sur un réseau domestique typique. (Pour les curieux : cela peut permettre d’accéder aux conteneurs de dev depuis votre MacBook !!!)

⚠️ Avertissement #1 : Les ports publiés par Docker peuvent contourner les règles de pare‑feu que vous pensiez protéger l’hôte, en particulier avec UFW sur Ubuntu/Debian. Cela ne rend pas chaque règle de pare‑feu inutile, mais cela signifie que « UFW dit deny » n’est pas une preuve. Voir l’incident #690 : Docker contourne les règles ufw.

⚠️ Avertissement #2 : Lier les ports à des adresses IP locales (par ex. -p 127.0.0.1:8080:80) est la bonne valeur par défaut, mais les versions du moteur Docker antérieures à 28.0.0 comportaient des cas où des hôtes sur le même réseau L2 pouvaient encore atteindre les ports publiés sur localhost. Docker mentionne cette mise en garde dans son guide de publication de ports, et l’habitude de vérifier avec nmap décrite ci‑dessous reste pertinente.

Si vous êtes surpris d’apprendre cela, même surprise !

Lier aux IP locales reste une bonne pratique et a un impact réel dans les environnements cloud gérés et les réseaux spécialement configurés.

Exemple Docker Compose

Voici un fichier docker-compose.yml qui lie le service app à 127.0.0.1:8080 et connecte les deux conteneurs au réseau personnalisé backend.

docker-compose.yml
networks:
backend:
services:
app:
networks:
- backend
ports:
# Bind to localhost if possible
- "127.0.0.1:8080:8080"
# ... other settings
database:
image: postgres:17.1
# No ports needed; accessible inside backend network.
networks:
- backend

Bonnes pratiques réseau

🛡️ Contrôles d’accès

Les contrôles d’accès sont une partie critique de la sécurisation de vos services Docker. Cela inclut la limitation des capacités et permissions des conteneurs, la restriction d’accès au socket Docker, etc.

Limitation des capacités des conteneurs

Une autre pratique solide de contrôle d’accès consiste à limiter les capacités de vos conteneurs. Cela réduit le rayon d’impact de plusieurs menaces, de l’escalade de privilèges au détournement de trafic. Ce n’est pas un champ de force, mais cela retire des permissions dont la plupart des conteneurs n’ont jamais besoin.

Qu’est‑ce que les capacités ? Des permissions ou habilitations nommées définies par le noyau Linux. (La page de manuel capabilities en donne la liste complète.) Elles incluent, par exemple, CAP_CHOWN (changer le propriétaire d’un fichier), CAP_NET_ADMIN (configurer les interfaces réseau), CAP_KILL (tuer n’importe quel processus), etc.

Les deux méthodes pour déterminer les capacités nécessaires sont :

  1. Essais et erreurs : Cette méthode plus lente mais efficace vous fait démarrer sans aucune capacité, puis les ré‑ajouter une à une jusqu’à ce que votre application fonctionne.
  2. Recherche de travaux existants : Cherchez « nom‑du‑projet cap_drop Dockerfile » ou « nom‑du‑projet cap_drop docker‑compose.yml » pour voir si d’autres ont déjà fait le travail. Un LLM peut suggérer un point de départ, mais traitez‑le comme une hypothèse jusqu’à ce que vous testiez le conteneur et lisiez la documentation de l’image.

Bonnes pratiques des capacités

Example: Drop/Limit Capabilities
services:
database:
image: postgres:17.1
networks: [ db-network ]
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_READ_SEARCH
- FOWNER
- SETGID
- SETUID
db-admin:
image: dpage/pgadmin4:4.1
networks: [ db-network ]
ports:
- "8081:80"
# ... other settings
networks:
db-network:

Vos services peuvent maintenant communiquer entre eux via le réseau db-network. Docker Compose créera ce réseau automatiquement.

Utilisez l’option --external/external: pour rejoindre un réseau pré‑existant. Omettez‑la pour créer un nouveau réseau.

Accès au socket Docker

⚠️ Avertissement : docker.sock équivaut pratiquement à un accès administrateur de l’hôte

⚠️ L’option :ro n’affecte pas les I/O transitant par le socket !

Cela ne fait que garantir que le chemin du socket lui‑même est monté en lecture‑seule. Les appels d’API envoyés via ce socket peuvent toujours créer des conteneurs, monter des chemins de l’hôte, et réaliser d’autres actions très excitantes que vous n’aviez probablement pas l’intention de déléguer.

Bonnes pratiques pour le socket

Blocage par pays !

Parfois utile, mais ce n’est pas une vraie frontière de sécurité.

En parlant de l’entité géopolitique, pas de la musique…

Si vous hébergez des applications principalement pour votre famille et vos amis locaux, vous pouvez bloquer le trafic provenant de pays d’où vous n’attendez aucun accès. Vous pouvez aussi n’autoriser que le trafic en provenance des pays que vous attendez. Cela réduit le bruit ; cela n’arrête pas les VPN, les proxys, les botnets ou les acteurs patients.

Jetez un œil à ce script pour bloquer tout le trafic en provenance de la Chine :

block-china.sh
curl -fsSL https://www.ipdeny.com/ipblocks/data/countries/cn.zone | \
while read line; do ufw deny from $line to any; done

De même, vous pouvez n’autoriser que le trafic en provenance des États‑Unis :

allow-usa.sh
curl -fsSL https://www.ipdeny.com/ipblocks/data/countries/us.zone | \
while read line; do ufw allow from $line to any; done

Renforcement du proxy d’hébergement CloudFlare

Si votre serveur domestique est protégé derrière une IP CloudFlare (proxy), vous pouvez restreindre l’accès uniquement aux IP CloudFlare et à votre réseau local.

C’est un peu similaire au blocage par pays ci‑dessus, mais avec un contrôle beaucoup plus strict.

whitelist-ingress-from-cloudflare.sh
ufw default deny incoming # Bloquer tout le trafic entrant !!!
ufw default allow outgoing # Autoriser tout le trafic sortant
ufw allow ssh # Autoriser SSH
# Autoriser l’accès pour le sous‑réseau local (de préférence un DMZ/VLAN dédié pour les services hébergés)
ufw allow from 10.0.0.0/8 to any port 443
# Autoriser les IP CloudFlare
curl -fsSL https://www.cloudflare.com/ips-v4 | \
while read line; do ufw allow from $line to any port 443; done
# Ajouter le support IPv6
# curl -fsSL https://www.cloudflare.com/ips-v6 | \
# while read line; do ufw allow from $line to any port 443; done

Pour tester les changements basés sur la géolocalisation, un VPN disposant de points d’accès dans le pays ciblé peut être pratique. Voir davantage dans la section Monitoring & Verification.

Sécurité au niveau de l’application

Une fois que votre réseau et votre hôte sont renforcés, vous constaterez qu’il reste encore du travail à faire.

Il faut maintenant envisager la couche « application » de vos services eux‑mêmes.

Cette base de données possède‑t‑elle un mot de passe valide ? Ce conteneur automatise‑t‑il HTTPS/certificats ? L’application intègre‑t‑elle une authentification native ? Existe‑t‑il des limites sur les adresses e‑mail pouvant s’inscrire ? Y a‑t‑il des identifiants par défaut ou des variables d’environnement à modifier ?

La seule façon de savoir est de vérifier. Dans ce cas, commencez par le README et les autres fichiers clés comme docker-compose.yml, Dockerfile et .env.*. Faites‑le tant pour le projet que, idéalement, pour ses services de support (par ex. Postgres, Redis, etc.).

Proxy inverse

Une autre couche de défense est l’authentification basique. Ne l’utilisez jamais sans HTTPS. Pour les services hérités, placer une authentification basique devant une route d’administration suffit souvent à bloquer les requêtes opportunistes et les robots non authentifiés qui tenteraient d’accéder directement au service.

/etc/nginx/conf.d/secure-admin.conf
location /admin {
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://internal_admin:80;
proxy_set_header X-Real-IP $remote_addr;
}

Générer les identifiants :

Terminal window
htpasswd -c /etc/nginx/.htpasswd admin

Avec un proxy à authentification basique, les attaquants doivent franchir un obstacle supplémentaire — nom d’utilisateur et mot de passe— avant d’atteindre votre service interne.

Une autre option consiste à recourir à un service comme Traefik ou Caddy qui peut automatiser HTTPS et l’authentification basique pour vous.

Si vous devez gérer de nombreux domaines et services via une interface graphique, je recommande Nginx Proxy Manager.

🔍 Surveillance & Vérification

C’est l’étape la plus importante et la plus négligée. Vous pouvez disposer du meilleur pare‑feu, du meilleur réseau et des meilleures pratiques, mais si vous ne validez pas le tout, vous ne savez pas si cela fonctionne.

De plus, connaître quelques commandes — ou savoir où les trouver — peut faire la différence entre prévenir une intrusion ou la subir. Le plaisir de se sentir hacker est un bonus. (Pour les détails et des exemples, sautez directement à la section Surveillance & Vérification.)

Ne faites pas confiance, vérifiez deux fois

Vérifiez vos ports

⚠️ IMPORTANT : ne scannez pas des hôtes qui ne vous appartiennent pas.

Que vous soyez sur un réseau domestique ou un VPS, vous devez savoir quels ports sont exposés au monde.

Il existe 2 méthodes :

Test depuis l’extérieur de votre réseau

Vous aurez besoin de votre adresse IP publique actuelle, facilement obtenable via des services comme ifconfig.me : curl https://ifconfig.me. Vous pouvez aussi la retrouver dans le tableau de bord de votre fournisseur d’hébergement.

Get Public IP
curl -fsSL https://ifconfig.me
# --> CURRENT PUBLIC IP

Une fois que vous avez votre IP publique, il faut se connecter depuis un réseau externe. Vous pouvez utiliser l’ordinateur d’un ami, un téléphone/point d’accès 5G, ou un serveur dédié.

nmap External Scan
target_host="$(curl -fsSL https://ifconfig.me)"
# Note : assurez‑vous que `target_host` correspond à l’adresse IP souhaitée
# Scanner des ports spécifiques :
nmap -A -p 80,443,8080 --open --reason $target_host
# Top 100 des ports :
nmap -A --top-ports 100 --open --reason $target_host
# Tous les ports
nmap -A -p1-65535 --open --reason $target_host

Testez depuis votre réseau interne

Entraînez‑vous avec nmap, scannez votre réseau local ou l’un de vos serveurs, vérifiez votre routeur, votre imprimante, votre réfrigérateur intelligent.

Exemples de commandes de scan

Terminal window
# Scanner votre localhost pour tous les ports ouverts
nmap -sT localhost
# Scanner l’IP privée de votre machine pour les services
nmap -sV 192.168.1.10
# Trouver les détails des services sur votre réseau
nmap -sn 192.168.0.0/24
nmap -sn 10.0.0.0/24
# Ou sur un réseau Docker 172.18.0.1/16
nmap -sn 172.18.0.1/16
nmap Scan
% nmap -A --open --reason 192.168.0.87
Starting Nmap 7.95 ( https://nmap.org ) at 2025-01-06 13:51 MST
Nmap scan report for dev02.local (192.168.0.87)
Host is up, received syn-ack (0.0067s latency).
Not shown: 995 closed tcp ports (conn-refused)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 9.6p1 Ubuntu 3ubuntu13.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|_ 256 {FINGERPRINT} (ED25519)
80/tcp open http syn-ack Caddy httpd
|_http-server-header: Caddy
|_http-title: Dev02.DanLevy.net
443/tcp open ssl/https syn-ack
|_http-title: Dev02.DanLevy.net
1234/tcp open http syn-ack Node.js Express framework
|_http-cors: GET POST PUT DELETE PATCH
|_http-title: Dev02.DanLevy.net (application/json; charset=utf-8).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.36 seconds

Voir les ports ouverts

Familiarisez‑vous avec lsof — disponible sous macOS et Linux. Il fournit un état réseau granulaire ainsi que l’activité disque.

lsof Commands
# Surveiller un port spécifique
sudo lsof -i:80 -Pn
# Surveiller les connexions ESTABLISHED
sudo lsof -i -Pn | grep ESTABLISHED
# Voir les sockets LISTEN
sudo lsof -i -Pn | grep LISTEN
# Afficher les noms réseau au lieu des adresses IP (peut être très lent à cause des résolutions DNS inverses)
sudo lsof -i -P | grep LISTEN
# Surveiller toutes les connexions réseau
sudo watch -n1 "lsof -i -Pn"

Exemple de sortie

analyse nmap des écouteurs

Surveillance des fichiers

Pour identifier quels processus consomment le plus de bande passante du disque, vous pouvez utiliser iotop :

Terminal window
sudo iotop

Pour observer les changements de fichiers individuels, utilisez inotifywait sous Linux ou fswatch sous macOS :

Cela peut être utile pour détecter un comportement non autorisé ou étrange, que ce soit par dossier ou à l’échelle du système.

Terminal window
# Surveiller tous les changements de fichiers dans un répertoire
sudo inotifywait -m /path/to/directory

Sous macOS, vous pouvez recourir à fswatch :

Installez-le avec brew install fswatch

Terminal window
fswatch -r /path/to/directory

⏰ Astuces souvent négligées

  1. Limitation du débit pour les tentatives d’authentification et tout autre point d’entrée critique. Que ce soit via le module limit_req de Nginx ou fail2ban pour l’accès SSH, le throttling contre les attaques par force brute est probablement une bonne idée. Je dis probablement parce qu’à l’ère de l’IPv6 et des botnets bon marché, la situation n’est plus ce qu’elle était.

  2. Utiliser des volumes en lecture seule quand c’est possible :

services: webapp: volumes:

Associé à d’autres bonnes pratiques (utilisateurs non root, permissions de dossiers limitées), l’option de montage `:ro` ajoute une couche de protection contre les modifications accidentelles et certaines tentatives d’écriture depuis l’intérieur du conteneur. Elle ne protège pas l’hôte contre un processus qui possède déjà des privilèges plus larges.
3. **Auditer régulièrement l’accès aux conteneurs**.
Si un conteneur n’a pas besoin d’un secret, d’un port ou d’un montage, supprimez‑le !
4. **Méfiance envers le Wi‑Fi indésirable**
Vous ne donneriez jamais votre mot de passe Wi‑Fi à n’importe qui, n’est‑ce pas ? Sauf peut‑être à quelques amis… ou à la famille. On ne sait jamais quelles applications ils utilisent et lesquelles pourraient divulguer votre SSID et votre mot de passe au grand public.
### Réseau domestique vs. Fournisseur public vs. Tunneling
1. **Isolation virtuelle/DMZ** : pour les serveurs domestiques, placez‑les sur un VLAN ou une DMZ séparée si possible. Cela empêche vos appareils internes d’être accessibles depuis un serveur compromis.
- Utilisez un routeur distinct ou un VLAN dédié pour votre serveur domestique.
- Utilisez un réseau Wi‑Fi séparé pour votre serveur domestique.
- Utilisez un sous‑réseau distinct pour votre serveur domestique.
2. **Fournisseurs Cloud** : Hetzner, Vultr, DigitalOcean, Linode, AWS, Azure et Google Cloud offrent tous des fonctionnalités de pare‑feu différentes.
- Certains fournisseurs et services bloquent les ports par défaut. D’autres proposent des options d’activation ou des modules complémentaires. Consultez la documentation de votre fournisseur.
- De nombreux fournisseurs proposent des services avancés de surveillance et de détection des menaces.
3. **VPN et Tunneling** : Envisagez d’utiliser une solution de type VPN ou un service de tunneling pour connecter les services de façon sécurisée à travers Internet sans les exposer publiquement.
- TailScale, ngrok, ZeroTier.
- WireGuard, OpenVPN.
{/* 3. **Hardening Against Internal/Lateral Attacks**: One infected device can compromise an entire network. Segmenting Docker services on custom networks, using hardware, UFW rules, and blocking unneeded ports can all help reduce risk (when properly configured.) */}
## 🚀 Checklist de Production
- [ ] **Secrets** : Tous les secrets sont générés aléatoirement et stockés de façon sécurisée
- [ ] **Mises à jour** : Stratégie de mise à jour des conteneurs documentée et automatisée. (C’est acceptable si cela se résume à quelques commandes dans un fichier texte.)
- [ ] **Réseau** : Seuls les ports nécessaires sont exposés, les réseaux internes sont configurés.
- [ ] **Règles de pare‑feu** : Refus par défaut, autorisations explicites, blocage de pays si besoin.
- [ ] **Proxy inverse** : Nginx, Caddy ou Traefik peuvent ajouter une couche d’authentification basique.
- [ ] **Jetons Canary** : Placez‑les près des fichiers sensibles et des identifiants que vous enquêteriez réellement en cas de modification.
- [ ] **Surveillance** : Connaissez vos systèmes avec `nmap`, `lsof`, `inotifywait`, `glances`, etc.
- [ ] **Stratégie de sauvegarde** : Testée, de préférence automatisée, et hors site.
- [ ] **Moindre privilège** : Utilisateurs non root dans les conteneurs, volumes en lecture‑seule.
## 📚 Lectures complémentaires
- [Docker Security Best Practices](https://docs.docker.com/develop/security-best-practices/)
- [OWASP Docker Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html)
- [CIS Docker Benchmark](https://www.cisecurity.org/benchmark/docker)
- [Canarytokens.org for Canary Tokens](https://canarytokens.org/)
## Remerciements
Un grand merci à quelques Redditors assidus :
- <em className="cite">[u/JCBird1012](https://www.reddit.com/user/JCBird1012/) - [thread](https://www.reddit.com/r/selfhosted/comments/1hv8jn6/comment/m5rvlzi/).</em>
- <em className="cite">[u/Salzig](https://www.reddit.com/user/Salzig/)</em>
- <em className="cite">[u/Myelrond](https://www.reddit.com/user/myelrond/)</em>
- <em className="cite">[u/shrimpdiddle](https://www.reddit.com/user/shrimpdiddle/)</em>
- <em className="cite">[u/troeberry](https://www.reddit.com/user/troeberry/)</em>
Merci de votre lecture ! J’espère que ce guide vous a été utile. Si vous avez des questions ou des suggestions, n’hésitez pas à me contacter sur mes réseaux sociaux ci‑dessous, ou cliquez sur le lien `Edit on GitHub` pour créer une PR ! ❤️