La façon la plus rapide de ruiner votre après-midi est de taper docker compose up -d alors que votre shell cible le mauvais démon.
Vous pensez redémarrer une stack de dev ; la production est d’accord en silence et fait exactement ce que vous avez demandé.
Les contextes Docker existent pour empêcher cela. Ils vous donnent des endpoints nommés et inspectables avec un basculement explicite, ainsi que
suffisamment de métadonnées pour faire de « où est-ce que je déploie ? » une question à laquelle vous pouvez répondre avant que quoi que ce soit ne prenne feu.
Pourquoi les contextes existent (et pourquoi DOCKER_HOST est une arme à feu)
Si vous utilisez Docker depuis assez longtemps, vous avez probablement utilisé DOCKER_HOST ou saupoudré
docker -H tcp://... dans des scripts comme assaisonnement. Ça marche. Mais cela crée aussi un état invisible, inauditable
et difficile à gérer en contrôle de version. Votre terminal devient une source de risque.
Les contextes Docker corrigent cela en faisant de la « sélection du démon cible » un concept de première classe : vous lui donnez un nom, vous pouvez le lister, l’inspecter,
l’exporter/importer, et forcer vos outils à l’utiliser. Cette dernière partie est importante en réponse à incident :
vous voulez moins de variables implicites globales, pas plus.
Les contextes unifient aussi plusieurs types d’endpoints. En pratique vous verrez :
- Local (par défaut) vers Docker Desktop de votre poste ou le socket du démon Linux.
- SSH vers un hôte distant sans exposer l’API TCP de Docker sur Internet.
- TCP/TLS pour des configurations héritées ou des réseaux contrôlés (prudence, on en reparle plus bas).
- Métadonnées d’orchestrateur (historiquement pour Swarm/Kubernetes ; aujourd’hui, surtout pour tenir la comptabilité des endpoints).
Un contexte n’est pas « juste de la commodité ». C’est une barrière de sécurité. C’est aussi un outil de responsabilité :
vous pouvez construire des workflows où « prod » est quelque chose que vous devez explicitement sélectionner, pas un accident dans lequel vous tombez.
Blague #1 : La seule chose plus permanente qu’une solution temporaire est une CLI Docker pointée vers la production.
Faits intéressants et rapide historique
- L’API distante de Docker est antérieure aux contextes : le contrôle distant initial reposait surtout sur
DOCKER_HOSTet l’API TCP, ce qui rendait les déploiements « oups » courants. - Les contextes sont devenus courants avec la CLI Docker v19.03, quand les équipes ont commencé à traiter plusieurs environnements comme la norme, pas l’exception.
- Les contextes SSH s’appuient sur le client OpenSSH : vous bénéficiez de l’agent forwarding, de la vérification known_hosts et de votre config SSH existante (ainsi que de ses aspérités).
- Docker Desktop utilise une abstraction semblable en interne pour router les commandes vers son démon basé sur VM ; les contextes rendent ce concept explicite pour vous.
- Swarm a été un moteur précoce pour « multiples endpoints, une seule CLI », même si beaucoup d’équipes sont passées à Kubernetes ou aux plateformes managées par la suite.
- Le démon est un pouvoir proche du root : un utilisateur qui peut parler au socket Docker peut typiquement devenir root sur cet hôte. Les contextes ne changent pas cela ; ils vous aident juste à pointer ce pouvoir délibérément.
- Les contextes sont stockés côté client (dans votre répertoire de config Docker), ce qui explique pourquoi l’export/import est utile pour les laptops, runners CI éphémères et boîtes de secours.
- Compose respecte les contextes :
docker composeparle à ce que le CLI a configuré, donc un « mauvais contexte » affecte tout votre flux de travail.
Modèle mental : ce qu’est vraiment un contexte
Pensez à un contexte Docker comme à un tuple nommé :
(endpoint, auth, TLS/SSH plumbing, metadata).
Ce n’est pas le moteur. Ce n’est pas un cluster. Ce n’est pas une variable d’environnement qu’on oublie.
C’est un objet de configuration sauvegardé sur disque que la CLI consulte avant d’agir.
Ce qu’il contient
Quand vous inspectez un contexte, vous verrez typiquement :
- Endpoints : généralement
dockeravec unHosttel queunix:///var/run/docker.sockoussh://user@host. - Matériel TLS (si vous utilisez TCP/TLS) : certificats et flags de vérification.
- Orchestrateur : souvent des champs
swarmoukubernetesselon l’époque ; dans beaucoup de configurations modernes c’est présent mais inutilisé. - Description : que vous devriez vraiment remplir, parce que les humains ont aussi besoin de garde-fous.
Priorité : qui gagne ?
Cela importe parce que les pannes de production adorent les bugs de priorité. Grosso modo :
docker --context X ...l’emporte pour cette invocation.DOCKER_CONTEXTpeut écraser le contexte « courant ».docker context use Xdéfinit le contexte courant pour les commandes futures.DOCKER_HOSTpeut contourner complètement les contextes pour certains outils ou scripts, selon leur implémentation.
Avis tranché : interdire DOCKER_HOST dans les shells interactifs. Autorisez-le uniquement dans de l’automatisation strictement contrôlée,
et même là, préférez --context pour la clarté.
Une citation fiable des ops
« L’espoir n’est pas une stratégie. » — Gene Kranz (idée paraphrasée)
Les contextes sont la façon d’arrêter d’« espérer » que vous parlez au bon démon.
Commandes de base utiles en production
Vous n’avez pas besoin de mémoriser 50 sous-commandes. Vous avez besoin d’une poignée que vous pouvez exécuter sous pression,
et de comprendre ce que la sortie implique.
Règle d’or
Avant toute commande destructive (rm, down, system prune, volume rm, « on va juste redéployer »),
faites un contrôle de contexte. Faites-en un tic.
Noms à adopter
dev,staging,prod(ennuyeux, efficace)prod-eu-west,prod-us-eastsi vous opérez réellement dans plusieurs régionsbuildkitoubuildersi vous utilisez des builders distants
Évitez les noms trop astucieux. Votre futur vous en pleine rotation d’astreinte n’en sera pas impressionné.
Tâches pratiques : 12+ choses que vous ferez réellement
Ci-dessous des tâches d’opérateur réelles avec commandes, sortie d’exemple, ce que ça signifie et la décision à en tirer.
Traitez-les comme des exercices de mémoire musculaire.
Task 1: List contexts and identify the current one
cr0x@server:~$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
staging Staging host via SSH ssh://deploy@stg-01
prod Production host via SSH ssh://deploy@prod-01
Ce que la sortie signifie : l’astérisque marque le contexte actif. La colonne « DOCKER ENDPOINT » vous indique comment la CLI atteindra le démon.
Décision : si vous vous apprêtez à toucher la production, vous devriez voir prod * et rien d’autre. Sinon, arrêtez-vous.
Task 2: Inspect a context before using it
cr0x@server:~$ docker context inspect prod
[
{
"Name": "prod",
"Metadata": {},
"Endpoints": {
"docker": {
"Host": "ssh://deploy@prod-01",
"SkipTLSVerify": false
}
},
"TLSMaterial": {},
"Storage": {
"MetadataPath": "/home/cr0x/.docker/contexts/meta/7c1a3c2b6f",
"TLSPath": "/home/cr0x/.docker/contexts/tls/7c1a3c2b6f"
}
}
]
Ce que la sortie signifie : il s’agit d’un contexte SSH ; le matériel TLS est vide parce que SSH fournit la sécurité du transport.
Décision : confirmez que la paire utilisateur/hôte est correcte et correspond à vos attentes de config SSH.
Si c’est root@prod-01, vous tenez une arme chargée.
Task 3: Switch contexts explicitly
cr0x@server:~$ docker context use staging
staging
cr0x@server:~$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default Current DOCKER_HOST based configuration unix:///var/run/docker.sock
staging * Staging host via SSH ssh://deploy@stg-01
prod Production host via SSH ssh://deploy@prod-01
Ce que la sortie signifie : votre shell est maintenant pointé vers staging pour toutes les commandes Docker futures.
Décision : dans des terminaux partagés (tmux, screen, jump hosts), affichez votre contexte dans le prompt ou la barre d’état. Le silence favorise les erreurs.
Task 4: Use a one-off context without changing your session
cr0x@server:~$ docker --context prod ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a12b3c4d5e6f nginx:1.25 "/docker-entrypoint.…" 2 days ago Up 2 days 0.0.0.0:80->80/tcp web
Ce que la sortie signifie : seule cette commande a ciblé prod ; votre contexte courant reste inchangé.
Décision : préférez ce schéma en automatisation et dans les runbooks à copier/coller.
C’est plus difficile d’« oublier où vous êtes ».
Task 5: Create a context via SSH (the sane default)
cr0x@server:~$ docker context create prod --docker "host=ssh://deploy@prod-01"
prod
cr0x@server:~$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
prod Production host via SSH ssh://deploy@prod-01
Ce que la sortie signifie : vous avez défini un endpoint distant sans exposer l’API TCP de Docker.
Décision : utilisez des contextes SSH sauf si vous avez une raison forte de ne pas le faire. « Parce que ça marchait en 2017 » n’est pas une bonne raison.
Task 6: Validate you’re talking to the right engine (cheap identity check)
cr0x@server:~$ docker --context prod info --format 'Name={{.Name}} Server={{.ServerVersion}} RootDir={{.DockerRootDir}}'
Name=prod-01 Server=25.0.3 RootDir=/var/lib/docker
Ce que la sortie signifie : vous avez extrait trois signaux d’identité : nom du démon, version et répertoire racine.
Décision : intégrez cela dans vos vérifications préalables. Si le nom est incorrect, vous êtes sur le mauvais hôte. Si la version est inattendue, prévoyez des différences de comportement.
Task 7: Detect “context works but SSH is lying to you” (host key / config mismatch)
cr0x@server:~$ docker --context prod ps
error during connect: Get "http://docker.example/v1.45/containers/json": command [ssh -o ConnectTimeout=30 -T -l deploy prod-01 docker system dial-stdio] exit status 255
Ce que la sortie signifie : la CLI a tenté d’exécuter docker system dial-stdio via SSH et a échoué. C’est le transport, pas Docker.
Décision : lancez une commande SSH simple à côté pour isoler le problème : si SSH échoue, réparez SSH (clés, bastion, host key).
Si SSH fonctionne mais Docker échoue, réparez les permissions du démon.
Task 8: Prove basic SSH connectivity (without Docker in the middle)
cr0x@server:~$ ssh -o BatchMode=yes deploy@prod-01 'hostname; id; docker version --format "{{.Server.Version}}"'
prod-01
uid=1001(deploy) gid=1001(deploy) groups=1001(deploy),998(docker)
25.0.3
Ce que la sortie signifie : l’utilisateur peut exécuter docker et fait partie du groupe docker. C’est essentiellement le pouvoir root sur cette machine.
Décision : traitez l’appartenance au groupe docker comme un accès sudo. Accordez-la délibérément, auditez-la et retirez-la quand ce n’est pas nécessaire.
Task 9: Export a context for a break-glass laptop or CI runner
cr0x@server:~$ docker context export prod -o prod.dockercontext
cr0x@server:~$ ls -l prod.dockercontext
-rw------- 1 cr0x cr0x 2840 Jan 3 10:12 prod.dockercontext
Ce que la sortie signifie : vous avez produit un bundle de contexte portable.
Décision : stockez-le comme un secret. S’il contient du matériel TLS, c’est littéralement un accès. Même avec des endpoints SSH uniquement, ce sont des métadonnées opérationnelles que vous ne voulez pas voir traîner.
Task 10: Import a context on another machine
cr0x@server:~$ docker context import prod -i prod.dockercontext
prod
cr0x@server:~$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
prod Production host via SSH ssh://deploy@prod-01
Ce que la sortie signifie : votre CLI sait maintenant comment atteindre la production de la même façon que la machine source.
Décision : pour CI, préférez générer des contextes à l’exécution (avec des identifiants éphémères) plutôt que d’importer des contextes longue durée.
Mais pour la réponse à incident, importer un contexte connu et sain est précieux.
Task 11: Remove a context you no longer trust
cr0x@server:~$ docker context rm staging
staging
cr0x@server:~$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
prod Production host via SSH ssh://deploy@prod-01
Ce que la sortie signifie : les métadonnées du contexte ont été supprimées côté client.
Décision : supprimez les contextes quand des hôtes sont décommissionnés, déplacés ou reconstruits. Les contextes obsolètes sont la façon dont on finit par déployer sur un hostname recyclé.
Task 12: Compare two environments quickly (images, containers, disk)
cr0x@server:~$ docker --context staging system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 18 6 5.2GB 2.7GB (51%)
Containers 9 6 210MB 0B (0%)
Local Volumes 14 9 22.4GB 3.1GB (13%)
Build Cache 0 0 0B 0B
Ce que la sortie signifie : vous obtenez une idée rapide de la pression sur le stockage et si un nettoyage est pertinent.
Décision : si les volumes dominent, n’appliquez pas un system prune impulsif. Vos données sont probablement dans des volumes. Planifiez un nettoyage ciblé.
Task 13: Run the same check on prod without switching contexts
cr0x@server:~$ docker --context prod system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 42 18 14.8GB 1.1GB (7%)
Containers 31 27 1.8GB 0B (0%)
Local Volumes 66 55 640.2GB 12.4GB (1%)
Build Cache 0 0 0B 0B
Ce que la sortie signifie : la production est fortement orientée volumes et difficilement récupérable. C’est normal pour des services stateful, et c’est un rappel que le disque est un plan de capacité, pas un bouton de nettoyage.
Décision : si des alertes disque sonnent, le pruning ne vous sauvera pas. Vous avez besoin de discipline sur le cycle de vie des volumes, de politiques de rétention, ou de disques plus grands.
Task 14: Verify a Compose deployment targets the intended host
cr0x@server:~$ docker --context prod compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
app-web-1 registry/app:web "/entrypoint.sh" web 3 hours ago Up 3 hours 0.0.0.0:443->443/tcp
app-db-1 postgres:16 "docker-entrypoint.s…" db 3 hours ago Up 3 hours 5432/tcp
Ce que la sortie signifie : Compose parle à prod. Les services en cours sont listés depuis ce démon.
Décision : quand vous n’êtes pas sûr de la cible de Compose, ne devinez pas — interrogez-la avec compose ps en utilisant --context.
Task 15: Diagnose “wrong context” from the prompt with an explicit marker
cr0x@server:~$ docker context show
prod
Ce que la sortie signifie : la CLI affiche le nom du contexte actif, rien d’autre.
Décision : intégrez cela dans votre prompt shell (PS1) ou votre barre tmux. Vous voulez que le contexte soit visible comme votre branche git courante.
Task 16: Check event stream on the remote daemon (great during incidents)
cr0x@server:~$ docker --context prod events --since 10m
2026-01-03T10:02:21.223456789Z container die a12b3c4d5e6f (exitCode=137, image=registry/app:web, name=app-web-1)
2026-01-03T10:02:24.019283746Z container start 9f8e7d6c5b4a (image=registry/app:web, name=app-web-1)
Ce que la sortie signifie : vous voyez de la rotation de cycle de vie des conteneurs ; exit 137 implique souvent un SIGKILL, fréquemment un OOM-kill ou un kill manuel.
Décision : si vous voyez des morts/restarts répétés, arrêtez de redéployer en panique. Regardez les limites mémoire, les logs du kernel OOM, ou les plantages applicatifs.
Blague #2 : « C’est juste un redémarrage rapide » est l’équivalent ops de « je prendrai juste un cookie ».
Sécurité et contrôle d’accès : tenir le démon en laisse
Les contextes Docker ne sécurisent rien magiquement. Ils facilitent l’utilisation de transports sécurisés et rendent plus difficile la réalisation d’erreurs stupides.
Le démon reste un plan de contrôle à haute privilège. Traitez-le comme SSH+sudo combinés.
Contexts SSH : le défaut que vous voulez
Avec les contextes ssh://, Docker exécute une commande helper sur l’hôte distant pour établir une connexion tunnelisée.
Cela vous apporte :
- Authentification par clé SSH et les garde-fous d’entreprise habituels (bastions, MFA, enregistrement de session).
- Vérification de la clé d’hôte (si vous ne l’avez pas désactivée comme un monstre).
- Pas besoin d’exposer le port de l’API TCP de Docker.
Contexts TCP : n’utilisez-les qu’avec TLS et une bonne raison
Si vous avez un environnement legacy qui exige tcp://host:2376 avec des certificats TLS, vous pouvez le représenter comme un contexte.
Mais rappelez-vous : l’API TCP de Docker non authentifiée est pratiquement « root sur le réseau ».
N’utilisez pas tcp://0.0.0.0:2375 à moins que votre modèle de menace soit « nous aimons le chaos ».
Moindre privilège (autant que Docker le permet)
Sur Docker Engine classique, quiconque accède à l’API Docker peut généralement monter le système de fichiers, exécuter des conteneurs privilégiés,
et escalader. Vos contrôles réels sont :
- Qui peut SSH vers l’hôte (et depuis où).
- Quel compte utilisateur est utilisé pour les contextes (des identités « deploy » séparées sont plus saines que des comptes personnels).
- Auditabilité des changements (events, logs système, pipelines de déploiement).
- Renforcement de l’hôte : AppArmor/SELinux, mode rootless quand possible, et paramètres du démon choisis avec soin.
Hygiène opérationnelle rentable
- Utilisez des contextes séparés pour des environnements distincts. Ne réutilisez pas « prod » pour plusieurs hôtes.
- Indiquez le nom de l’environnement dans la description du contexte et dans le banner distant (motd) si possible.
- Rendez le basculement de contexte explicite dans les runbooks et scripts : utilisez
--context. - Consignez « quel contexte a été utilisé » dans la sortie CI/CD. C’est banal et cela aide lors d’archéologies sans blâme.
Trois mini-histoires d’entreprise depuis le terrain
Incident causé par une fausse hypothèse : « default » voulait dire « dev »
Une équipe avait un jump host que « tout le monde utilisait » pour les opérations conteneurs. Il était maintenu par le groupe plateforme, et Docker y était installé.
L’hypothèse — jamais formulée, toujours implicite — était que le Docker du jump host était juste une commodité pour les outils. Les gens l’utilisaient pour exécuter des linters, pull des images, ou tester des fichiers Compose.
Un ingénieur a été paginé pour un problème de staging. Il a SSH sur le jump host, a lancé docker ps, a vu plein de conteneurs, et a conclu que staging était sain.
Puis il a lancé un nettoyage : docker system prune -af. La commande s’est terminée rapidement. Trop rapidement.
Le démon Docker du jump host n’était pas « local dev ». Il était configuré — via un vieux DOCKER_HOST exporté dans /etc/profile.d — pour pointer vers un moteur de production partagé.
Les conteneurs qu’il avait vus étaient des conteneurs de production. Le prune a supprimé des images et du cache de build en production, ce qui a déclenché une cascade de pulls d’images et de redémarrages en pleine charge.
Le postmortem n’a pas porté sur « qui a tapé la commande ». Il portait sur un état invisible et des hypothèses fragiles.
La correction a été simple et légèrement humiliante : supprimer le DOCKER_HOST global, définir des contextes, et mettre à jour le prompt du jump host pour afficher docker context show.
Ils ont aussi ajouté un petit wrapper : les commandes destructrices requièrent explicitement --context.
Ça n’a pas empêché toutes les erreurs, mais ça a évité toute cette classe d’incidents « je pensais être en dev ».
Optimisation qui a mal tourné : endpoint TCP distant « pour la vitesse »
Une autre organisation voulait accélérer les builds CI. Quelqu’un a remarqué que les contextes SSH ajoutent de la latence : établissement de session SSH, authentification, bizarreries occasionnelles avec les bastions.
Ils ont donc « optimisé » en exposant le démon Docker sur TCP à l’intérieur du réseau interne. C’était derrière un pare-feu, et ils ont promis d’ajouter TLS plus tard.
Ça a fonctionné. Les builds étaient plus rapides. L’équipe a célébré en augmentant les jobs parallèles, ce qui a augmenté la charge de l’API Docker, puis le CPU du démon, puis tout a ralenti à nouveau.
Entre-temps, « TLS plus tard » est devenu « TLS jamais », parce que la pipeline dépendait déjà de l’endpoint non sécurisé.
Le vrai retour de bâton est arrivé des mois plus tard lors d’un projet de segmentation réseau.
Les règles de firewall ont changé, et soudain un sous-ensemble de runners pouvait toujours atteindre l’API Docker tandis que d’autres ne le pouvaient pas. Les builds sont devenus instables, et les retry ont surchargé encore plus le démon.
Les ingénieurs ont passé des jours à déboguer « Docker est instable » alors que le problème était « vous avez construit un démon distant central avec une dépendance réseau fragile ».
La correction finale n’était pas glamour : revenir aux contextes SSH pour l’accès ad-hoc, et migrer la CI vers des builders par runner ou un cluster de build correctement géré.
Les contextes ont été conservés, mais la stratégie d’endpoint a changé. L’optimisation ciblait le mauvais goulot.
Leçon : retirer quelques millisecondes d’un canal de contrôle est rarement le vrai problème de performance. Vous voulez généralement localité, cache et capacité — pas un démon largement exposé.
Pratique ennuyeuse mais correcte qui a sauvé la mise : contextes explicites partout
Une équipe plus mature avait une règle : chaque commande de runbook incluait --context. Toutes.
C’était vaguement embêtant. Les gens se plaignaient. Puis ils ont arrêté d’y prêter attention, comme une ceinture de sécurité.
Un soir, ils ont eu un incident de production impliquant un volume de logs hors de contrôle qui a rempli le disque.
L’ingénieur d’astreinte avait staging ouvert dans un onglet et production dans un autre. Sous stress, c’est une recette pour des erreurs inter-environnements.
Ils ont suivi le runbook. Chaque commande était épinglée : docker --context prod ....
Ils ont inspecté l’utilisation des volumes, arrêté le conteneur bruyant correct, et l’ont redémarré avec une limite de log qu’ils avaient déjà validée en staging.
Le meilleur : lors du post-incident, ils avaient des logs de terminal et CI propres montrant exactement quel contexte avait été utilisé pour chaque action.
Pas de forensique approximative, pas de « je crois que j’étais en prod ». Le dossier était clair.
Les pratiques ennuyeuses n’ont pas de conférences. Elles vous gardent employé.
Playbook de diagnostic rapide (trouver le goulot vite)
Quand « Docker est lent » ou « le contexte distant est instable », ne changez pas les paramètres au hasard. Triez comme un adulte :
identifiez si le goulot est le transport, la santé du démon, les pulls d’images/registry,
le stockage, ou votre propre machine cliente.
Première étape : confirmez que vous debuggez la bonne cible
cr0x@server:~$ docker context show
prod
Décision : si le contexte n’est pas l’environnement que vous pensez, arrêtez. Corrigez cela d’abord. Tout le reste est du bruit.
Deuxième : mesurez la latence basique du plan de contrôle
cr0x@server:~$ time docker --context prod version
Client: Docker Engine - Community
Version: 25.0.3
API version: 1.45
...
real 0m0.612s
user 0m0.078s
sys 0m0.021s
Ce que ça signifie : moins d’une seconde c’est correct. Plusieurs secondes suggèrent des problèmes SSH/bastion/DNS ou un démon saturé.
Décision : si c’est lent, ne commencez pas par « tuning du stockage Docker ». Commencez par le réseau/SSH et la charge du démon.
Troisième : vérifiez la santé du démon et la pression sur les ressources
cr0x@server:~$ docker --context prod info | sed -n '1,35p'
Client:
Version: 25.0.3
Context: prod
Debug Mode: false
Server:
Containers: 31
Running: 27
Paused: 0
Stopped: 4
Images: 42
Server Version: 25.0.3
Storage Driver: overlay2
Logging Driver: json-file
Cgroup Driver: systemd
...
Décision : confirmez le storage driver, le logging driver et le nombre général de conteneurs/images. Si ces éléments diffèrent entre environnements, le comportement diffèrera aussi.
Quatrième : identifiez si le stockage est le vrai coupable
cr0x@server:~$ docker --context prod system df -v | sed -n '1,40p'
Images space usage:
REPOSITORY TAG IMAGE ID CREATED SIZE SHARED SIZE UNIQUE SIZE CONTAINERS
registry/app web 2aa1b3c4d5e6 3 hours ago 412.5MB 0B 412.5MB 4
...
Décision : si le churn d’images est élevé, concentrez-vous sur la vitesse de pull, la performance du registry et le caching.
Si les volumes dominent, travaillez sur le cycle de vie/la rétention et la performance du système de fichiers.
Cinquième : observez la rotation et les redémarrages des conteneurs
cr0x@server:~$ docker --context prod ps --format 'table {{.Names}}\t{{.Status}}\t{{.RunningFor}}'
NAMES STATUS RUNNING FOR
app-web-1 Up 3 hours (healthy) 3 hours
app-db-1 Up 3 hours 3 hours
worker-1 Restarting (1) 5 seconds 8 minutes
Décision : les boucles de redémarrage font tout paraître « lent » car le démon crée/détruit constamment des ressources.
Corrigez le conteneur en crash avant d’optimiser autre chose.
Sixième : si les contextes SSH échouent de façon intermittente, isolez SSH
cr0x@server:~$ ssh -o ServerAliveInterval=5 -o ServerAliveCountMax=2 deploy@prod-01 'echo ok'
ok
Décision : si ça décroche, votre problème est le chemin réseau, la stabilité du bastion, ou des timeouts SSH — pas les contextes Docker.
Erreurs courantes : symptôme → cause racine → correction
Mistake 1: “I deployed to the wrong host”
Symptôme : des changements de staging apparaissent en prod, ou des changements prod n’apparaissent nulle part où vous les attendez.
Cause racine : contexte courant implicite, ou DOCKER_HOST qui écrase ce que vous pensiez être actif.
Correction : utilisez docker --context ... dans les runbooks/scripts ; supprimez le DOCKER_HOST global ; affichez le contexte dans le prompt ; imposez la sélection explicite pour les actions destructrices.
Mistake 2: “docker context use prod” works, but commands hang
Symptôme : la CLI bloque sur ps, info, pull, ou compose up.
Cause racine : problème sur le chemin SSH (bastion, DNS, MTU), ou démon distant sous forte charge CPU/mémoire.
Correction : mesurez docker --context prod version ; testez SSH simple ; vérifiez la charge de l’hôte distant ; envisagez des keepalives SSH.
Mistake 3: “It says permission denied to the Docker daemon”
Symptôme : erreurs de contexte distant comme « permission denied while trying to connect to the Docker daemon socket. »
Cause racine : l’utilisateur distant peut SSH mais n’a pas accès à /var/run/docker.sock (pas dans le groupe docker, ou mismatch rootless daemon).
Correction : accordez la bonne appartenance de groupe (avec prudence), ou utilisez intentionnellement des endpoints Docker rootless ; validez avec ssh host 'docker ps'.
Mistake 4: “My context points to an old host after rebuild”
Symptôme : le contexte se connecte, mais vous voyez un démon tout neuf vide ou un nom/version d’engine inattendu.
Cause racine : hostname recyclé, DNS mis à jour, ou une nouvelle instance a pris ce nom.
Correction : validez l’identité avec docker info --format 'Name=...' ; épinglez la config SSH sur des host keys stables ; mettez à jour les contextes après les rebuilds.
Mistake 5: “Exported context works on one laptop but not another”
Symptôme : le contexte importé existe mais échoue à se connecter via SSH.
Cause racine : agent SSH/clefs différentes, config SSH différente, ou mismatch known_hosts.
Correction : assurez-vous que la machine importatrice a la bonne identité SSH et la bonne config ; testez avec SSH simple ; évitez de compter sur l’agent-forwarding dans l’automatisation.
Mistake 6: “Compose behaves differently than docker”
Symptôme : docker ps montre un environnement, mais docker compose en affecte un autre (ou inversement).
Cause racine : usage mixte de DOCKER_HOST, DOCKER_CONTEXT et du « contexte courant », ou exécution dans différents shells avec des vars d’env différentes.
Correction : standardisez sur --context ; affichez les vars d’env dans les shells de debug ; évitez d’exporter DOCKER_HOST dans les profils.
Mistake 7: “The context list shows ERROR”
Symptôme : docker context ls affiche une colonne erreur pour un contexte.
Cause racine : endpoint injoignable ou mal configuré ; la CLI Docker a tenté une validation et a échoué.
Correction : inspectez le contexte ; testez SSH ; recréez le contexte si la chaîne d’endpoint est erronée ; supprimez les contextes obsolètes.
Mistake 8: “We used TCP because it’s internal; now security is angry”
Symptôme : finding d’audit : API Docker exposée sans TLS, règles firewall larges, accès démon mystérieux.
Cause racine : design d’endpoint dicté par la commodité ; l’API distante traitée comme un service inoffensif.
Correction : migrez vers des contextes SSH ou des endpoints TLS-authentifiés ; restreignez les chemins réseau ; faites tourner les credentials ; traitez l’accès au démon comme un accès privilégié.
Checklists / plan étape par étape
Étape par étape : adopter les contextes sans casser tout le monde
- Inventaire des endpoints : listez où aboutissent actuellement les commandes Docker (laptops développeurs, jump hosts, runners CI).
- Supprimez les globals cachés : cherchez
DOCKER_HOSTdans les profils shell et les injections d’environnement CI. - Créez des contextes nommés : au minimum
dev,staging,prod. Utilisez des endpoints SSH. - Ajoutez des descriptions : incluez environnement, région et ownership. Les humains se trompent ; les métadonnées aident.
- Standardisez les runbooks : mettez à jour chaque commande pour inclure
--context. - Rendez le contexte visible : intégration prompt/tmux pour toujours savoir où vous êtes.
- Définissez une procédure break-glass : flux d’export/import de contexte, gestion des credentials et attentes d’audit.
- Discipline CI/CD : utilisez des contextes explicites ou des endpoints explicites par job ; évitez de dépendre du « contexte courant ».
- Faites tourner les accès : si vous utilisiez TCP sans TLS historiquement, considérez-le compromis et faites une rotation.
- Entraînez-vous avec des drills : pratiquez « basculer contexte, vérifier identité, exécuter la commande » jusqu’à ce que ce soit automatique.
Checklist opérationnelle : avant d’exécuter quelque chose de risqué
- Exécutez
docker context show. - Exécutez
docker info --format 'Name={{.Name}}'contre ce contexte. - Confirmez que vous êtes dans le bon onglet/fenêtre de terminal (ça semble bête ; ça évite des pannes).
- Préférez
docker --context X ...pour la commande risquée. - Pour le nettoyage : inspectez d’abord
docker system df; ne prunez pas aveuglément.
Checklist de durcissement : rendre plus difficile la mauvaise action
- Comptes séparés pour deploy vs admin ; n’utilisez pas de clefs SSH personnelles pour l’automatisation.
- Utilisez des contextes SSH ; évitez d’exposer l’API TCP de Docker.
- Imposez la vérification des host keys ; gérez known_hosts centralement quand c’est pertinent.
- Limitez qui peut atteindre les hôtes Docker (ACL réseau, bastions, proxies à identité).
- Auditez l’appartenance au groupe
dockercomme vous auditez les sudoers.
FAQ
1) Un contexte Docker est-il la même chose qu’un contexte Kubernetes ?
Non. Les contextes Kubernetes vivent dans kubeconfig et sélectionnent clusters/namespaces/utilisateurs pour kubectl.
Les contextes Docker sélectionnent les endpoints de la CLI Docker (socket local, SSH, TCP/TLS). Idée similaire, univers différent.
2) Dois-je utiliser docker context ou DOCKER_HOST ?
Utilisez les contextes pour les humains et la plupart de l’automatisation. Réservez DOCKER_HOST aux outils legacy que vous ne pouvez pas changer,
et limitez-le strictement par processus, ne l’exportez pas dans les profils.
3) Quelle est la façon la plus sûre de gérer l’accès production ?
Utilisez des contextes SSH avec un compte deploy dédié, des chemins réseau verrouillés (bastion), et une gestion des clés auditée.
Rendez chaque commande prod explicite via --context prod.
4) Pourquoi Docker sur SSH semble parfois plus lent ?
Parce qu’il fait plus : mise en place SSH, authentification, et une connexion stdio tunnelisée. Si la latence est insupportable,
la vraie solution est généralement de meilleurs chemins réseau, des control masters persistants, ou de rapprocher les jobs de build du démon.
5) Puis-je stocker les contextes dans git ?
Ne commitez pas les contextes exportés. Ils peuvent contenir du matériel TLS sensible et des endpoints opérationnels.
Stockez plutôt les instructions pour créer les contextes, et générez-les à l’exécution.
6) Comment éviter les surprises de « contexte courant » dans les scripts ?
Utilisez docker --context NAME sur chaque commande. Les scripts doivent être déterministes.
Si un script dépend de l’état de votre shell interactif, ce n’est pas un script ; c’est une suggestion.
7) Les contextes Docker peuvent-ils aider pour des rollouts multi-régions ?
Oui. Créez des contextes comme prod-eu-west et prod-us-east, puis exécutez les mêmes commandes explicitement contre chacun.
Soyez discipliné sur le nommage et les vérifications d’identité.
8) Pourquoi docker context ls affiche-t-il une erreur pour un contexte ?
L’endpoint est injoignable ou mal configuré, ou Docker a tenté un test de connexion et a échoué.
Inspectez le contexte, validez SSH manuellement, et recréez-le si la chaîne d’hôte est fausse.
9) Les contextes sont-ils partagés entre utilisateurs sur la même machine ?
Généralement non. Les contextes sont stockés dans le répertoire de config Docker de l’utilisateur. C’est bien : ça évite des couplages inter-utilisateurs inattendus.
Cela signifie aussi que vous devez les gérer par compte sur les jump boxes partagés.
10) L’utilisation des contextes rend-elle Docker « sûr » pour des hôtes multi-tenant ?
Les contextes sont un sélecteur côté client. La sécurité multi-tenant dépend de la configuration du démon, de l’isolation kernel, et du contrôle d’accès.
Les contextes vous aident à éviter les erreurs d’opérateur ; ils ne fournissent pas d’isolation entre locataires.
Prochaines étapes à faire cette semaine
Si vous opérez plus d’un hôte Docker, vous êtes déjà en zone « cibles multiples ». Agissez en conséquence.
- Créez des contextes pour chaque environnement en utilisant des endpoints SSH. Nommez-les simplement.
- Rendez le contexte visible dans votre prompt shell ou la barre tmux.
- Mettez à jour les runbooks pour que chaque commande épingle
--context. - Retirez le
DOCKER_HOSTglobal des environnements interactifs et des jump hosts partagés. - Ajoutez un pré-vol d’identité :
docker --context X info --format 'Name={{.Name}} Server={{.ServerVersion}}'. - Auditez les accès : qui peut atteindre les hôtes prod, qui est dans le groupe docker, et comment les clefs sont gérées.
Les contextes n’empêcheront pas toutes les pannes. Ils empêcheront les erreurs stupides. Ce sont celles qui reviennent vous appeler à 2h du matin.