Contexte Docker : gérer plusieurs hôtes comme un pro

Cet article vous a aidé ?

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_HOST et 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 compose parle à 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 docker avec un Host tel que unix:///var/run/docker.sock ou ssh://user@host.
  • Matériel TLS (si vous utilisez TCP/TLS) : certificats et flags de vérification.
  • Orchestrateur : souvent des champs swarm ou kubernetes selon 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_CONTEXT peut écraser le contexte « courant ».
  • docker context use X définit le contexte courant pour les commandes futures.
  • DOCKER_HOST peut 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-east si vous opérez réellement dans plusieurs régions
  • buildkit ou builder si 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

  1. Inventaire des endpoints : listez où aboutissent actuellement les commandes Docker (laptops développeurs, jump hosts, runners CI).
  2. Supprimez les globals cachés : cherchez DOCKER_HOST dans les profils shell et les injections d’environnement CI.
  3. Créez des contextes nommés : au minimum dev, staging, prod. Utilisez des endpoints SSH.
  4. Ajoutez des descriptions : incluez environnement, région et ownership. Les humains se trompent ; les métadonnées aident.
  5. Standardisez les runbooks : mettez à jour chaque commande pour inclure --context.
  6. Rendez le contexte visible : intégration prompt/tmux pour toujours savoir où vous êtes.
  7. Définissez une procédure break-glass : flux d’export/import de contexte, gestion des credentials et attentes d’audit.
  8. Discipline CI/CD : utilisez des contextes explicites ou des endpoints explicites par job ; évitez de dépendre du « contexte courant ».
  9. Faites tourner les accès : si vous utilisiez TCP sans TLS historiquement, considérez-le compromis et faites une rotation.
  10. 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 docker comme 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.

  1. Créez des contextes pour chaque environnement en utilisant des endpoints SSH. Nommez-les simplement.
  2. Rendez le contexte visible dans votre prompt shell ou la barre tmux.
  3. Mettez à jour les runbooks pour que chaque commande épingle --context.
  4. Retirez le DOCKER_HOST global des environnements interactifs et des jump hosts partagés.
  5. Ajoutez un pré-vol d’identité : docker --context X info --format 'Name={{.Name}} Server={{.ServerVersion}}'.
  6. 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.

← Précédent
Goulets d’étranglement sans hystérie : mesurer la limite réelle
Suivant →
Serveurs dans des placards surchauffés : comment « pas de ventilation » tue la disponibilité

Laisser un commentaire