[{"data":1,"prerenderedAt":443},["ShallowReactive",2],{"deck:docker":3},{"deck":4,"reason":441,"status":442},{"id":5,"stem":6,"matiere":7,"name":8,"punchline":9,"deckStatus":10,"customMessages":11,"sources":21,"cards":25},"docker","decks/docker","informatique","Docker","Ça marche sur ma machine, et sur la tienne aussi","publié",{"low":12,"medium":15,"high":18},[13,14],"Image, conteneur, couche : on pose le vocabulaire","Le Dockerfile se lit de haut en bas, le cache aussi",[16,17],"Les ports et les volumes rentrent","Forme exec, pas forme shell : ça y est",[19,20],"Multi-stage, non-root, digest épinglé : image propre","Le démon n'a plus de secret",[22],{"title":23,"url":24},"Docker Docs","https://docs.docker.com/",[26,34,42,50,58,67,74,81,88,96,111,122,130,138,145,153,164,171,178,190,197,204,211,219,226,234,241,248,255,266,278,285,292,299,307,315,322,333,341,348,359,366,377,384,391,398,409,418,425,434],{"id":27,"tags":28,"question":30,"quick_answer":31,"details":32,"difficulty":33},"dkr-001",[7,5,29],"conteneurs","Qu'est-ce qu'un **conteneur** ?","Un processus isolé qui partage le noyau de la machine hôte","Un conteneur n'est pas une petite machine virtuelle : c'est un **processus ordinaire** du système hôte, mais isolé (son propre système de fichiers, son propre réseau, ses propres PID) grâce aux namespaces et cgroups Linux.\n\nIl démarre en quelques millisecondes parce qu'il n'y a aucun OS à booter.",3,{"id":35,"tags":36,"question":37,"quick_answer":38,"details":39,"dependsOn":40,"difficulty":41},"dkr-002",[7,5,29],"Qu'est-ce qu'une **machine virtuelle** virtualise, que le conteneur ne virtualise pas ?","Le matériel : une VM embarque son propre noyau et son propre OS","Une VM tourne au-dessus d'un hyperviseur, avec un noyau complet à elle. Un conteneur réutilise le noyau de l'hôte.\n\nConséquence : une VM démarre en secondes/minutes et pèse des Go ; un conteneur démarre en millisecondes et pèse des Mo. L'isolation d'une VM est en revanche plus forte.\n\nSur macOS et Windows, Docker Desktop fait tourner les conteneurs **dans une VM Linux** cachée, puisque le noyau hôte n'est pas Linux.",[27],5,{"id":43,"tags":44,"question":46,"quick_answer":47,"details":48,"dependsOn":49,"difficulty":33},"dkr-003",[7,5,45],"images","Qu'est-ce qu'une **image** Docker ?","Un modèle immuable, en lecture seule, à partir duquel on lance des conteneurs","L'image contient le système de fichiers (binaires, librairies, code) et des métadonnées (commande par défaut, ports, variables). Elle est constituée de **couches** empilées.\n\nAnalogie classique : l'image est la classe, le conteneur est l'objet instancié.",[27],{"id":51,"tags":52,"question":53,"quick_answer":54,"details":55,"dependsOn":56,"difficulty":57},"dkr-004",[7,5,45],"Qu'est-ce que la **couche d'écriture** d'un conteneur ?","Une fine couche propre au conteneur, ajoutée au-dessus de l'image en lecture seule","Lancer un conteneur = prendre l'image (lecture seule) et poser par-dessus une couche où vont toutes ses modifications. Dix conteneurs depuis la même image partagent les couches de l'image, chacun a sa couche d'écriture.\n\nElle disparaît avec le conteneur : c'est pour ça que les données durables vont dans un volume.",[43],4,{"id":59,"tags":60,"question":62,"quick_answer":63,"details":64,"dependsOn":65,"difficulty":66},"dkr-005",[7,5,61],"dockerfile","Qu'est-ce qu'un **Dockerfile** ?","Un fichier texte d'instructions pour construire une image","Chaque ligne est une instruction (`FROM`, `RUN`, `COPY`, `CMD`…). `docker build` les exécute dans l'ordre et produit une image.\n\nC'est la recette ; l'image est le plat ; le conteneur est l'assiette servie.",[43],2,{"id":68,"tags":69,"question":70,"quick_answer":71,"details":72,"dependsOn":73,"difficulty":66},"dkr-006",[7,5,61],"Rôle de l'instruction **FROM** dans un Dockerfile ?","Définit l'image de base sur laquelle on construit","Toujours la première instruction (hors `ARG` qui peut la précéder). Exemple : `FROM node:22-alpine`.\n\n`FROM scratch` désigne une image vide, utilisée pour des binaires statiques (Go, Rust).",[59],{"id":75,"tags":76,"question":77,"quick_answer":78,"details":79,"dependsOn":80,"difficulty":57},"dkr-007",[7,5,61],"Rôle de l'instruction **RUN** dans un Dockerfile ?","Exécute une commande au moment du build et crée une nouvelle couche","Exemple : `RUN apt-get update && apt-get install -y curl`.\n\nChaque `RUN` ajoute une couche à l'image. D'où l'habitude de chaîner les commandes avec `&&` et de nettoyer dans le même `RUN` (`rm -rf /var/lib/apt/lists/*`) : un fichier supprimé dans une couche suivante reste présent dans la couche précédente et pèse toujours dans l'image.",[59],{"id":82,"tags":83,"question":84,"quick_answer":85,"details":86,"dependsOn":87,"difficulty":57},"dkr-008",[7,5,61],"Rôle de l'instruction **CMD** dans un Dockerfile ?","La commande par défaut du conteneur, remplaçable par les arguments de docker run","`CMD [\"node\", \"app.js\"]` : si on lance `docker run monimage`, le conteneur exécute `node app.js`. Si on lance `docker run monimage sh`, le `sh` **remplace** entièrement le CMD.\n\nUn seul `CMD` par Dockerfile : si plusieurs sont écrits, seul le dernier compte.",[59],{"id":89,"tags":90,"question":91,"quick_answer":92,"details":93,"dependsOn":94,"difficulty":95},"dkr-009",[7,5,61],"Rôle de l'instruction **ENTRYPOINT** dans un Dockerfile ?","L'exécutable fixe du conteneur : les arguments de docker run s'y ajoutent au lieu de le remplacer","`ENTRYPOINT [\"python\"]` puis `docker run monimage script.py` exécute `python script.py`.\n\nQuand `ENTRYPOINT` et `CMD` sont tous deux présents, `CMD` fournit les **arguments par défaut** de l'entrypoint. Pour outrepasser l'entrypoint lui-même : `docker run --entrypoint sh monimage`.",[82],6,{"id":97,"tags":98,"question":99,"quick_answer":100,"details":101,"dependsOn":102,"difficulty":103,"sources":104},"dkr-010",[7,5,61],"Dans un Dockerfile, quelle différence entre `CMD [\"node\", \"app.js\"]` et `CMD node app.js` ?","Forme exec (tableau) : node est PID 1. Forme shell : c'est /bin/sh -c qui est PID 1","En **forme shell**, la commande est enveloppée dans `/bin/sh -c`. Le shell devient le processus 1 et, par défaut, ne transmet pas les signaux à son enfant : un `docker stop` envoie SIGTERM au shell, l'application ne le reçoit jamais, et Docker la tue brutalement au bout de 10 secondes.\n\nEn **forme exec**, l'application est directement PID 1 et reçoit SIGTERM : arrêt propre. Toujours préférer la forme exec.",[82],7,[105,108],{"title":106,"url":107},"Docker Docs — JSONArgsRecommended (forme shell et signaux)","https://docs.docker.com/reference/build-checks/json-args-recommended/",{"title":109,"url":110},"Docker Docs — docker container stop","https://docs.docker.com/reference/cli/docker/container/stop/",{"id":112,"tags":113,"question":114,"quick_answer":115,"details":116,"dependsOn":117,"difficulty":33,"sources":118},"dkr-011",[7,5,61],"Rôle de l'instruction **COPY** dans un Dockerfile ?","Copie des fichiers du contexte de build vers l'image","`COPY package.json ./` ou `COPY . .`\n\nIl existe aussi `ADD`, qui fait la même chose **plus** la décompression automatique d'archives tar locales et le téléchargement d'URL. La doc Docker recommande `COPY` par défaut : un comportement explicite, sans surprise. `ADD` se réserve au cas précis où l'on veut l'extraction d'une archive.",[59],[119],{"title":120,"url":121},"Docker Docs — Building best practices, ADD or COPY","https://docs.docker.com/build/building/best-practices/",{"id":123,"tags":124,"question":126,"quick_answer":127,"details":128,"dependsOn":129,"difficulty":57},"dkr-020",[7,5,125],"cli","Dans `docker run -p 8080:80 nginx`, quel port est celui de l'hôte ?","8080 : l'ordre est toujours hôte:conteneur","Le conteneur écoute sur 80 ; la machine expose 8080 et redirige. Piège classique : inverser les deux.\n\nAutres options courantes du même `docker run` : `-d` (détaché, le terminal est rendu tout de suite), `--name web` (nom lisible, sinon Docker en génère un comme `vibrant_turing`). Si l'image n'est pas présente localement, `docker run` la télécharge d'abord.",[51],{"id":131,"tags":132,"question":134,"quick_answer":135,"details":136,"dependsOn":137,"difficulty":41},"dkr-012",[7,5,61,133],"reseau","L'instruction **EXPOSE 80** rend-elle le port 80 accessible depuis l'hôte ?","Non : EXPOSE est de la documentation, c'est -p qui publie le port","`EXPOSE` note dans les métadonnées de l'image que le conteneur écoute sur ce port. Rien n'est ouvert pour autant.\n\nPour atteindre le port depuis l'hôte : `docker run -p 8080:80 monimage`. L'option `-P` (majuscule) publie tous les ports `EXPOSE` sur des ports hôte aléatoires.",[59,123],{"id":139,"tags":140,"question":141,"quick_answer":142,"details":143,"dependsOn":144,"difficulty":57},"dkr-013",[7,5,45],"Qu'est-ce qu'une **couche** (layer) d'image Docker ?","Le résultat d'une instruction du Dockerfile, empilé en lecture seule sur les précédentes","Chaque instruction qui modifie le système de fichiers (`RUN`, `COPY`, `ADD`) produit une couche. L'image finale est la pile de ces couches, fusionnées à l'affichage par un système de fichiers en union (overlay2).\n\nLes couches sont **partagées** entre images : dix images basées sur `debian:bookworm` ne stockent la base qu'une fois sur le disque.",[43],{"id":146,"tags":147,"question":149,"quick_answer":150,"details":151,"dependsOn":152,"difficulty":95},"dkr-014",[7,5,45,148],"performance","Pourquoi copier `package.json` et lancer `npm install` **avant** de copier le reste du code source ?","Pour que le cache de build survive aux modifications du code","Le cache fonctionne couche par couche : dès qu'une instruction change (ou que les fichiers qu'elle copie changent), **toutes les suivantes** sont reconstruites.\n\nSi `COPY . .` vient avant `RUN npm install`, chaque changement d'une ligne de code réinstalle toutes les dépendances. En copiant d'abord `package.json` seul, l'installation n'est refaite que si les dépendances changent. Ordre général : du plus stable au plus volatil.",[139],{"id":154,"tags":155,"question":156,"quick_answer":157,"details":158,"dependsOn":159,"difficulty":57,"sources":160},"dkr-016",[7,5,61],"Que désigne le `.` dans `docker build -t monapp:1.0 .` ?","Le contexte de build : le dossier envoyé au démon Docker","Le démon ne voit que ce contexte (BuildKit ne transfère que les fichiers réellement référencés, le builder historique envoyait tout). `COPY` ne peut copier que ce qui est dans ce contexte (pas de `COPY ../autre-dossier`).\n\n`-t` donne un nom et un tag à l'image produite.",[59],[161],{"title":162,"url":163},"Docker Docs — BuildKit","https://docs.docker.com/build/buildkit/",{"id":165,"tags":166,"question":167,"quick_answer":168,"details":169,"dependsOn":170,"difficulty":33},"dkr-015",[7,5,61],"À quoi sert le fichier **.dockerignore** ?","À exclure des fichiers du contexte de build (node_modules, .git, secrets…)","Même syntaxe que `.gitignore`. Sans lui, un `COPY . .` embarque `node_modules` et `.git` dans l'image : image gonflée, cache invalidé à chaque changement, et risque de copier un `.env` dans l'image.",[154],{"id":172,"tags":173,"question":174,"quick_answer":175,"details":176,"dependsOn":177,"difficulty":41},"dkr-017",[7,5,45],"Qu'est-ce qu'un **build multi-stage** ?","Un Dockerfile à plusieurs FROM, où l'image finale ne garde que les artefacts du stage de build","```\nFROM node:22 AS build\nWORKDIR /app\nCOPY . .\nRUN npm ci && npm run build\n\nFROM nginx:alpine\nCOPY --from=build /app/dist /usr/share/nginx/html\n```\n\nLes compilateurs, dépendances de dev et sources restent dans le premier stage. L'image livrée ne contient que le résultat : plus petite, moins de surface d'attaque.",[139],{"id":179,"tags":180,"question":182,"quick_answer":183,"details":184,"dependsOn":185,"difficulty":41,"sources":186},"dkr-018",[7,5,45,181],"pieges","Que signifie le tag **latest** sur une image ?","Rien de spécial : c'est juste le tag par défaut, pas forcément la version la plus récente","`latest` est appliqué quand on ne précise pas de tag au `build` ou au `pull`. Il ne pointe vers la dernière version que si quelqu'un l'a poussé ainsi. Et `docker run nginx` réutilise le `latest` déjà présent en local sans consulter le registre : il faut un `docker pull` explicite pour le rafraîchir.\n\nEn production : toujours un tag explicite (`nginx:1.27.2`) ou un digest (`@sha256:…`), pour des déploiements reproductibles.",[43],[187],{"title":188,"url":189},"Docker Docs — docker container run, option --pull","https://docs.docker.com/reference/cli/docker/container/run/",{"id":191,"tags":192,"question":193,"quick_answer":194,"details":195,"dependsOn":196,"difficulty":57},"dkr-019",[7,5,45],"Comment se nomme complètement une image, par exemple `ghcr.io/org/app:1.2` ?","registre / dépôt : tag","- **Registre** : `ghcr.io` (absent = Docker Hub, `docker.io`)\n- **Dépôt** : `org/app` (sur Docker Hub, `nginx` seul = image officielle `library/nginx`)\n- **Tag** : `1.2` (absent = `latest`)\n\n`docker pull` télécharge depuis le registre, `docker push` y envoie. Il faut d'abord `docker login`.",[43],{"id":198,"tags":199,"question":200,"quick_answer":201,"details":202,"dependsOn":203,"difficulty":33},"dkr-021",[7,5,125],"Que fait l'option `--rm` de `docker run` ?","Supprime automatiquement le conteneur quand il s'arrête","Sans `--rm`, un conteneur arrêté reste sur le disque (visible avec `docker ps -a`) avec sa couche d'écriture. Pratique pour un conteneur jetable : `docker run --rm -it python:3.12 python`.",[123],{"id":205,"tags":206,"question":207,"quick_answer":208,"details":209,"dependsOn":210,"difficulty":66},"dkr-022",[7,5,125],"Différence entre `docker ps` et `docker ps -a` ?","ps : conteneurs en cours. ps -a : tous, y compris les arrêtés","Un conteneur qui a crashé au démarrage n'apparaît pas dans `docker ps`. Premier réflexe de debug : `docker ps -a` pour voir son statut (`Exited (1)`), puis `docker logs \u003Cnom>`.",[123],{"id":212,"tags":213,"question":215,"quick_answer":216,"details":217,"dependsOn":218,"difficulty":33},"dkr-023",[7,5,125,214],"debug","Commande pour ouvrir un shell dans un conteneur **en cours d'exécution** ?","docker exec -it \u003Cconteneur> sh","`exec` lance un processus supplémentaire dans le conteneur existant. `-i` garde l'entrée standard ouverte, `-t` alloue un terminal.\n\n`sh` plutôt que `bash` : les images Alpine n'ont pas bash. À ne pas confondre avec `docker run`, qui crée un **nouveau** conteneur.",[123],{"id":220,"tags":221,"question":222,"quick_answer":223,"details":224,"dependsOn":225,"difficulty":66},"dkr-024",[7,5,125,214],"Commande pour lire la sortie (stdout/stderr) d'un conteneur ?","docker logs \u003Cconteneur> (avec -f pour suivre en direct)","Docker capture ce que le processus principal écrit sur stdout et stderr. D'où la règle : une application conteneurisée **logue sur la sortie standard**, pas dans un fichier.\n\n`--tail 100` pour les 100 dernières lignes, `--since 10m` pour les 10 dernières minutes.",[123],{"id":227,"tags":228,"question":230,"quick_answer":231,"details":232,"dependsOn":233,"difficulty":41},"dkr-025",[7,5,229],"stockage","Que deviennent les fichiers écrits dans un conteneur quand on le **supprime** ?","Perdus avec sa couche d'écriture, sauf s'ils sont dans un volume","La couche d'écriture appartient au conteneur. `docker rm` l'efface. Un `docker stop` puis `docker start` la conserve, mais un conteneur recréé (après mise à jour d'image, par exemple) repart de zéro.\n\nToute donnée qui doit survivre (base de données, uploads) va dans un **volume** ou un **bind mount**.",[51],{"id":235,"tags":236,"question":237,"quick_answer":238,"details":239,"dependsOn":240,"difficulty":57},"dkr-026",[7,5,229],"Qu'est-ce qu'un **volume** Docker ?","Un espace de stockage persistant géré par Docker, monté dans un conteneur","`docker run -v pgdata:/var/lib/postgresql/data postgres` crée (ou réutilise) le volume nommé `pgdata`. Docker le stocke sous `/var/lib/docker/volumes/` ; on ne manipule pas ce chemin à la main.\n\nLe volume survit à la suppression du conteneur. `docker volume ls` les liste, `docker volume rm` en supprime un.",[227],{"id":242,"tags":243,"question":244,"quick_answer":245,"details":246,"dependsOn":247,"difficulty":57},"dkr-027",[7,5,229],"Qu'est-ce qu'un **bind mount** ?","Un dossier de l'hôte monté tel quel dans le conteneur","`docker run -v $(pwd)/src:/app/src monimage` : le dossier `src` de la machine apparaît dans le conteneur, modifications dans les deux sens, en temps réel.\n\nC'est l'outil du développement (rechargement à chaud). En production, on préfère les volumes nommés : indépendants de l'arborescence de l'hôte et gérés par Docker.",[227],{"id":249,"tags":250,"question":251,"quick_answer":252,"details":253,"dependsOn":254,"difficulty":41},"dkr-028",[7,5,133],"Pourquoi créer un réseau Docker (`docker network create`) plutôt qu'utiliser le bridge par défaut ?","Sur un réseau défini par l'utilisateur, les conteneurs se contactent par leur nom (DNS intégré)","Sur le `bridge` par défaut, les conteneurs ne se voient que par IP. Sur un réseau créé par l'utilisateur, `web` peut appeler `http://api:3000` : Docker résout `api` vers le conteneur de ce nom.\n\nDocker Compose crée automatiquement un tel réseau pour chaque projet, c'est pour ça que les services s'y appellent par leur nom.",[123],{"id":256,"tags":257,"question":258,"quick_answer":259,"details":260,"dependsOn":261,"difficulty":41,"sources":262},"dkr-029",[7,5,133],"Que fait `--network host` ?","Le conteneur utilise directement la pile réseau de l'hôte, sans isolation ni -p","Le conteneur écoute sur les ports de la machine comme un processus normal. Plus de mapping de ports, meilleures performances réseau, mais plus d'isolation.\n\nNatif sous Linux. Sous Docker Desktop (Mac/Windows), à activer dans les réglages (Resources > Network, depuis la 4.34) ; sinon l'« hôte » vu par le conteneur est la VM Linux, pas ta machine.",[249],[263],{"title":264,"url":265},"Docker Docs — Host network driver","https://docs.docker.com/engine/network/drivers/host/",{"id":267,"tags":268,"question":270,"quick_answer":271,"details":272,"dependsOn":273,"difficulty":33,"sources":274},"dkr-030",[7,5,269],"compose","Qu'est-ce que **Docker Compose** ?","Un outil pour définir et lancer une application multi-conteneurs depuis un fichier YAML","Dans `compose.yaml` (ou `docker-compose.yml`), on déclare les services (web, api, db), leurs images, ports, volumes, variables et réseaux. `docker compose up -d` lance tout, `docker compose down` arrête et supprime.\n\nLa commande moderne est `docker compose` (plugin, v2) ; `docker-compose` v1, l'ancien binaire Python, est en fin de vie depuis juin 2023 (certaines distros exposent un `docker-compose` qui est en fait la v2).",[123],[275],{"title":276,"url":277},"Docker Blog — Compose v2 and v1 deprecation","https://www.docker.com/blog/new-docker-compose-v2-and-v1-deprecation/",{"id":279,"tags":280,"question":281,"quick_answer":282,"details":283,"dependsOn":284,"difficulty":41},"dkr-035",[7,5,61],"Rôle de l'instruction **HEALTHCHECK** ?","Définit une commande périodique qui dit si le conteneur est en bonne santé","`HEALTHCHECK --interval=30s CMD curl -f http://localhost/ || exit 1`\n\nLe statut (`healthy` / `unhealthy`) apparaît dans `docker ps` et sert à Compose (`condition: service_healthy`) ou à un orchestrateur. Docker ne redémarre **pas** tout seul un conteneur `unhealthy` : il se contente de le signaler.",[59],{"id":286,"tags":287,"question":288,"quick_answer":289,"details":290,"dependsOn":291,"difficulty":95},"dkr-031",[7,5,269,181],"Dans Compose, `depends_on: [db]` garantit-il que la base est **prête** quand `api` démarre ?","Non : seulement que le conteneur db est démarré, pas que Postgres accepte des connexions","`depends_on` ordonne le **démarrage des conteneurs**, pas la disponibilité du service. Pour attendre que la base réponde : un `healthcheck` sur `db` et `depends_on: db: condition: service_healthy` sur `api`.\n\nÀ défaut, l'application doit savoir réessayer sa connexion au démarrage.",[267,279],{"id":293,"tags":294,"question":295,"quick_answer":296,"details":297,"dependsOn":298,"difficulty":57},"dkr-032",[7,5,61],"Portée d'un **ARG** dans un Dockerfile ?","Le build uniquement : la valeur n'existe plus dans le conteneur","`ARG VERSION=1.0` se surcharge avec `docker build --build-arg VERSION=2.0`. Sert à paramétrer le build (version de base, cible). Disponible dans les instructions qui suivent sa déclaration, jamais au runtime.",[59],{"id":300,"tags":301,"question":303,"quick_answer":304,"details":305,"dependsOn":306,"difficulty":41},"dkr-033",[7,5,302],"securite","Pourquoi ajouter une instruction **USER** dans un Dockerfile ?","Pour ne pas exécuter l'application en root dans le conteneur","Par défaut, le processus tourne en **root** (UID 0). Si l'application est compromise, l'attaquant est root dans le conteneur, et une faille d'isolation suffit alors pour atteindre l'hôte.\n\n`RUN adduser --system app` puis `USER app` avant le `CMD`. Les images officielles comme `node` fournissent déjà un utilisateur `node`.",[59],{"id":308,"tags":309,"question":311,"quick_answer":312,"details":313,"dependsOn":314,"difficulty":57},"dkr-036",[7,5,310],"architecture","Qui exécute réellement les conteneurs quand on tape `docker run` ?","Le démon dockerd : la commande docker n'est qu'un client qui lui parle via une API","Architecture client-serveur. Le client `docker` envoie une requête HTTP au démon (socket Unix local, ou TCP distant via `DOCKER_HOST`). Le démon délègue ensuite à **containerd**, qui lance le conteneur avec **runc**.\n\nC'est pour ça qu'on peut piloter un Docker distant avec le même client.",[27],{"id":316,"tags":317,"question":318,"quick_answer":319,"details":320,"dependsOn":321,"difficulty":103},"dkr-034",[7,5,302],"Pourquoi donner accès à `/var/run/docker.sock` à un conteneur est-il dangereux ?","Qui parle au démon Docker peut lancer un conteneur privilégié : c'est root sur l'hôte","Le socket Unix est l'API du démon, qui tourne en root. Un conteneur qui le monte peut créer un autre conteneur avec `--privileged` et le système de fichiers de l'hôte monté dedans.\n\nMême logique pour le groupe `docker` sur une machine : en faire partie équivaut à un accès root sans mot de passe.",[308],{"id":323,"tags":324,"question":325,"quick_answer":326,"details":327,"dependsOn":328,"difficulty":41,"sources":329},"dkr-037",[7,5,310],"Qu'est-ce que l'**OCI** (Open Container Initiative) ?","Les standards ouverts du format d'image et du runtime de conteneur","Fondée en 2015 par Docker et d'autres acteurs sous la Linux Foundation. Trois spécifications : **image-spec** (format des images), **runtime-spec** (comment lancer un conteneur) et **distribution-spec** (l'API des registres).\n\nConséquence : une image construite avec Docker tourne avec Podman, containerd ou CRI-O, donc sous Kubernetes. `runc` est l'implémentation de référence du runtime.",[308],[330],{"title":331,"url":332},"Open Container Initiative — Overview","https://opencontainers.org/about/overview/",{"id":334,"tags":335,"question":337,"quick_answer":338,"details":339,"dependsOn":340,"difficulty":57},"dkr-038",[7,5,336],"linux","Quel mécanisme du noyau Linux assure l'**isolation** d'un conteneur (ce qu'il voit) ?","Les namespaces","Un namespace donne au processus une vue privée d'une ressource : **pid** (ses propres numéros de processus, il se croit PID 1), **net** (ses interfaces réseau), **mnt** (son système de fichiers), **uts** (son hostname), **ipc**, **user**.\n\nÀ distinguer des cgroups, qui limitent ce que le conteneur **consomme**.",[27],{"id":342,"tags":343,"question":344,"quick_answer":345,"details":346,"dependsOn":347,"difficulty":57},"dkr-039",[7,5,336],"Quel mécanisme du noyau Linux **limite les ressources** d'un conteneur (CPU, mémoire) ?","Les cgroups (control groups)","`docker run --memory=512m --cpus=1.5` se traduit en règles cgroup. Si le conteneur dépasse sa limite mémoire, le noyau le tue (OOM kill, code de sortie 137).\n\nSans limite, un conteneur peut consommer toute la mémoire de l'hôte.",[27],{"id":349,"tags":350,"question":351,"quick_answer":352,"details":353,"dependsOn":354,"difficulty":57,"sources":355},"dkr-040",[7,5,125],"Que fait `--restart unless-stopped` ?","Redémarre le conteneur s'il plante ou au reboot, sauf si on l'a arrêté à la main","Politiques disponibles : `no` (défaut), `on-failure[:n]`, `always`, `unless-stopped`. La différence `always` / `unless-stopped` : après un `docker stop` explicite, `always` relance quand même le conteneur au redémarrage du démon, `unless-stopped` non.\n\nIndispensable pour un service sur un serveur sans orchestrateur.",[123],[356],{"title":357,"url":358},"Docker Docs — Start containers automatically","https://docs.docker.com/engine/containers/start-containers-automatically/",{"id":360,"tags":361,"question":362,"quick_answer":363,"details":364,"dependsOn":365,"difficulty":33},"dkr-041",[7,5,125],"Que fait `docker system prune` ?","Le ménage : conteneurs arrêtés, réseaux inutilisés, images orphelines et cache de build pendant","Docker ne nettoie jamais tout seul : les vieilles images et les conteneurs arrêtés s'accumulent jusqu'à remplir le disque. `docker system df` montre l'espace utilisé.\n\n`prune -a` supprime aussi les images non utilisées par un conteneur (pas seulement les `\u003Cnone>`) et tout le cache de build. `--volumes` touche aux volumes : à manier avec prudence.",[205],{"id":367,"tags":368,"question":369,"quick_answer":370,"details":371,"dependsOn":372,"difficulty":41,"sources":373},"dkr-042",[7,5,45],"Pourquoi les images basées sur **Alpine** sont-elles si petites ?","Distribution minimaliste (~5 Mo) avec musl et busybox au lieu de glibc et coreutils","Sur disque, `node:22` pèse plus d'un Go, `node:22-alpine` autour de 150 Mo. Moins de paquets = moins de surface d'attaque et des pulls plus rapides.\n\nContrepartie : `musl` n'est pas `glibc`, certains binaires précompilés ou modules natifs ne fonctionnent pas. Alternative sans shell du tout : les images **distroless** de Google.",[68],[374],{"title":375,"url":376},"Docker Hub — alpine","https://hub.docker.com/_/alpine",{"id":378,"tags":379,"question":380,"quick_answer":381,"details":382,"dependsOn":383,"difficulty":33},"dkr-043",[7,5,125,214],"Commande pour voir toute la configuration d'un conteneur (IP, montages, variables) ?","docker inspect \u003Cconteneur>","Renvoie un gros JSON. Pour une valeur précise : `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web` (le champ `IPAddress` à la racine n'est rempli que sur le bridge par défaut).\n\nFonctionne aussi sur une image, un volume ou un réseau.",[123],{"id":385,"tags":386,"question":387,"quick_answer":388,"details":389,"dependsOn":390,"difficulty":57},"dkr-044",[7,5,45],"Comment garantir qu'on déploie **exactement** la même image qu'en test, indépendamment des tags ?","La référencer par son digest : image@sha256:…","Un tag peut être réécrit (quelqu'un repousse `app:1.2`). Le digest est le hash du contenu de l'image : immuable par construction. `docker pull nginx@sha256:abc…` ou `docker images --digests` pour les lire.\n\nC'est ce que font les outils de supply chain et les lockfiles d'images.",[179],{"id":392,"tags":393,"question":394,"quick_answer":395,"details":396,"dependsOn":397,"difficulty":57},"dkr-045",[7,5,61],"Portée d'un **ENV** dans un Dockerfile ?","Le build et le runtime : la variable est vue par le processus du conteneur","`ENV NODE_ENV=production` est enregistrée dans l'image et visible par l'application. Modifiable au lancement : `docker run -e NODE_ENV=development`.\n\nElle est aussi lisible dans `docker inspect` : pas un endroit pour un secret.",[293],{"id":399,"tags":400,"question":401,"quick_answer":402,"details":403,"dependsOn":404,"difficulty":95,"sources":405},"dkr-046",[7,5,61,302],"Pourquoi ne pas passer un secret par **ARG** au build ?","Il reste visible dans l'historique de l'image (docker history)","Chaque instruction, avec ses arguments, est enregistrée dans les métadonnées de l'image. Un `--build-arg NPM_TOKEN=…` se retrouve en clair chez quiconque récupère l'image.\n\nLa bonne méthode : `RUN --mount=type=secret,id=npmrc …` avec `docker build --secret id=npmrc,src=.npmrc`. Le fichier est monté le temps de l'instruction et ne laisse aucune trace dans les couches.",[293],[406],{"title":407,"url":408},"Docker Docs — Build secrets","https://docs.docker.com/build/building/secrets/",{"id":410,"tags":411,"question":412,"quick_answer":413,"details":414,"dependsOn":415,"difficulty":57,"sources":416},"dkr-047",[7,5,61],"Que fait **ADD** que **COPY** ne fait pas ?","Extraire automatiquement une archive tar locale, et télécharger depuis une URL","`ADD app.tar.gz /opt/` décompresse ; `ADD https://… /tmp/` télécharge. Pratique mais implicite : on ne voit pas qu'une extraction a lieu.\n\nLa doc Docker recommande `COPY` par défaut et `ADD` seulement quand on veut l'extraction d'une archive.",[112],[417],{"title":120,"url":121},{"id":419,"tags":420,"question":421,"quick_answer":422,"details":423,"dependsOn":424,"difficulty":33},"dkr-048",[7,5,61],"Rôle de l'instruction **WORKDIR** ?","Fixe le dossier courant pour les instructions suivantes et pour le processus du conteneur","`WORKDIR /app` crée le dossier s'il n'existe pas ; les `COPY`, `RUN`, `CMD` qui suivent s'exécutent dedans. Toujours préférable à `RUN cd /app && …`, qui ne persiste pas d'une instruction à l'autre.",[59],{"id":426,"tags":427,"question":428,"quick_answer":429,"details":430,"dependsOn":431,"difficulty":57,"sources":432},"dkr-049",[7,5,125],"Différence entre `docker stop` et `docker kill` ?","stop envoie SIGTERM puis SIGKILL après 10 s ; kill envoie SIGKILL tout de suite","`stop` laisse à l'application le temps de fermer proprement (connexions, fichiers). Le délai se règle avec `-t`. `kill` tue sans sommation, à réserver à un conteneur bloqué.\n\nL'instruction `STOPSIGNAL` du Dockerfile change le signal envoyé par `stop` (utile pour nginx, qui attend `SIGQUIT`).",[97],[433],{"title":109,"url":110},{"id":435,"tags":436,"question":437,"quick_answer":438,"details":439,"dependsOn":440,"difficulty":33},"dkr-050",[7,5,269,229],"`docker compose down` supprime-t-il les volumes ?","Non : il faut ajouter -v pour les supprimer","`down` arrête et supprime les conteneurs et le réseau du projet, mais garde les volumes nommés : les données de la base survivent. `down -v` les efface aussi, c'est la commande du « je repars de zéro ».",[267,235],"ok",null,1792059302821]