# Docker ![Schema Docker Swarm](images/docker-wave-whale.svg "Schema Docker Swarm") __Introduction aux conteneurs Docker__ Maxime Poullain • Christian Tritten Un conteneur est un environnement d'exécution _maitrisé_ et _auto-suffisant_ qui _partage le noyau du système hôte_ et qui est _isolé_ du reste du système. ![Conteneurs](images/docker-container.png) Docker est une technologie qui permet d'embarquer une application dans un conteneur virtuel qui pourra s'exécuter sur n'importe quelle machine. ### A quoi ça peut servir ? * Cloisonner des applications (serveur web, de base de donnée, ...) * Exécuter un traitement ou un calcul ponctuel (par ex. compilation, tests unitaires, transcodage, etc...) * Multiplier rapidement le nombre d'instances d'une application (Orchestration : Docker Swarm, Kubernetes, etc...) ### Pour un développeur * Utiliser la même pile applicative lors des phases de développement et tests que celle qui tournera en production (et ainsi réduire les sources d'erreurs...) * Lancer plusieurs versions distinctes d'une même application sur sa machine (par ex. plusieurs stacks LAMP différentes) ![Les images Docker les plus populaires en 2020](images/most-popular-docker-official-images-in-2020.png) Source : https://www.docker.com/blog/docker-index-shows-continued-massive-developer-adoption-and-activity-to-build-and-share-apps-with-docker/ ### Principaux objectifs de Docker * Faciliter l'empaquetage et la distribution des applications. * Simplifier le déploiement et la mise à jour des applications. * Épouser les principes des philosophies devops et microservices. ![Build Ship Run](images/build-ship-run-any-app-anywhere.png) ## Conteneurisation - Un peu d'histoire ### 1979 * _Chroot_ est un utilitaire qui permet de changer la racine du système de fichiers pour un processus et ses enfants. * Il s'agit d'une des premières mise en oeuvre d'un concept d'isolation au sein des systèmes d'exploitation. ### 2000 * _Jails_ permet d'aller plus loin que _chroot_ en isolant les processus, les utilisateurs, et le réseau sur un système BSD. * Chaque jail est un environnement virtuel isolé à l'intérieur duquel on peut déléguer l'administration tout en conservant un bon niveau de sécurité sur le système hôte. ### 2001 * L'idée est ensuite reprise sur Linux avec Linux VServer qui permet de partitionner le réseau, la mémoire, et le système de fichier. ### 2002 * La technologie _Linux Namespaces_ qui permet de faire de l'isolation par processus commence à être intégré dans le noyau Linux. ### 2006 * Le projet _Process Containers_ est initié chez Google. * Il s'agit d'un ensemble de mécanismes permettant de limiter les ressources disponibles pour un processus. * Cette technologie, connue sous le nom de _Control Groups_ est intégrée dans le noyaux Linux. ### 2008 * _LXC_ (LinuX Containers) propose la première implémentation de conteneurs basée sur les Namespaces et les Control Groups. * Reste assez complexe au niveau utilisation. ### 2013 * _Docker_ voit le jour et est la première solution de conteneurisation vraiment simple à utiliser. ## Docker - Un peu d'histoire... ### 2008 ![Solomon Hykes](images/solomon-hykes.png) * Solomon Hykes créé la startup _dotCloud_ qui se spécialise comme fournisseur de solutions PaaS (Platform as a Service). ### 2010 - 2011 * Solomon Hykes commence à travailler sur le projet de conteneurisation de processus qui deviendra _Docker_. * dotCloud s'installe dans la Silicon Valley. ### 2013 - 2014 * Mars 2013, la technologie de conteneur de dotCloud est publié sous licence libre (Apache 2.0). * Dès fin 2013 le projet suscite sur Github un énorme engouement de la part des développeurs. * Fin 2013 Solomon Hykes décide de créer une nouvelle société entièrement dédiée au projet : _Docker Inc._ * En juin 2014, Docker Inc. publie la _version 1.0_ de Docker. ### 2014 - 2016 * Tous les grands noms du cloud, Amazon Web Services, Microsoft Azure, Google Cloud Platform, OVH, Redhat OpenShift... proposent des offres permettant d'exécuter des conteneurs Docker. * Docker devient le standard de facto pour exécuter des conteneurs sous Linux. * Les outils d'orchestration de conteneurs Docker commencent à apparaître et à se démocratiser. * En 2015, Docker participe à la création de la [Cloud Native Computing Foundation](https://www.cncf.io/) aux côtés de Google, IBM, Intel, et bien d'autres... * La mission de cette fondation est de populariser les infrastructures reposant sur les conteneurs et la notion de micro-services. ### 2017 * Fin 2017, Docker annonce le support de Kubernetes dans son offre Entreprise Edition 2.0. ### 2019 * Kubernetes a gagné la guerre des orchestrateurs. * [Mirantis fait l'acquisition de Docker Enterprise Platform](https://www.mirantis.com/company/press-center/company-news/mirantis-acquires-docker-enterprise/). ### Aujourd'hui * Les conteneurs sont massivement utilisés partout. * La kubecon est un des évènements annuels les plus marquants autour des conteneurs. ## Différences entre un conteneur et une VM ? * Une __machine virtuelle__ isole l'intégralité d'un système d'exploitation (kernel + userspace). * Un __conteneur__ isole uniquement le userspace et utilise directement le kernel du système hôte. * Le kernel (noyau du système d'exploitation) offre la possibilité de virtualiser ses différents sous-systèmes afin de ne présenter au conteneur qu'un sous-ensemble des ressources réellement disponibles. * On parle de virtualisation légère. ### De la VM au Conteneur ![conteneurs / vms](images/virtual-machine-vs-container.png) ### Changement du niveau d'abstraction ![Niveau d'abstraction](images/user-space-vs-Kernel-space-virtualization-vs-containerization.png) ### Communication processus <==> noyau ![Niveau d'abstraction](images/user-space-vs-kernel-space-simple-user-space.png) ![Niveau d'abstraction](images/user-space-vs-kernel-space-simple-container.png) ## L'outillage Docker ### Le Docker Engine ![Docker engine](images/docker-engine.png) ### containerd * C'est le moteur d'exécution de conteneurs développé par Docker. * Il respecte la spécification CRI. * Il tourne en tant que daemon sur le système hôte. * Il fournit les fonctionnalités pour récupérer et gérer en local les images Docker, gérer le réseau et le stockage. * Il pilote l'outil _runc_ pour les opérations de bas niveau qui concernent la création des conteneurs. ### containerd * Le projet a été offert par Docker à la [CNCF](https://www.cncf.io "Cloud Native Computing Foundation") en mars 2017. * https://containerd.io/ ![Docker Engine / Containerd / Runc](images/docker-engine-containerd-runc.png) Source : https://www.tutorialworks.com/difference-docker-containerd-runc-crio-oci/ ### Les images Docker * Docker fourni des outils permettant d'empaqueter d'une application sous la forme d'une image _légère_, _portable_ et _auto-suffisante_. * Ces outils facilitent la création, la mise à jour, le stockage et le transport des images. * Docker permet la création de nouvelles images de conteneurs _spécialisées_ à partir d'images de conteneurs plus _généralistes_. ### Le terme Docker est un raccourci utilisé un peu à tort et à travers pour nommer : * la société Docker * le Docker Engine * la CLI Docker (la commande `docker`) * une image Docker (respectant la spec OCI) * un conteneur Docker en cours d'exécution ## Quelques avantages des conteneurs Docker ### Image en lecture seule Un conteneur est instancié à partir d'une image en lecture seule. Dans le conteneur en exécution : * Pas de mises à jour. * Pas de correctifs. * Pas de modifications de configuration. * Pour mettre à jour le code de l'application ou appliquer un correctif, il faudra _créer une nouvelle image_ et _déployer un nouveau conteneur_. L'immuabilité de l'image permet des déploiements sûrs et reproductibles. * Pile applicative identique sur le poste du développeur et sur l'environnement de production. * Un conteneur aura le même comportement où qu'il soit déployé. * Moins de mauvaises surprises lors des passages en production. ### Démarrage rapide * Démarrer un conteneur est à peine un peu plus coûteux que de lancer un nouveau processus sur le système hôte. * En effet un conteneur Docker ne fait tourner que les processus nécessaires à l'exécution d'une application. (pas d'Init, pas de crontab, pas de...) * De plus grâce à la technique du _Copy-on-Write_ qui utilise des pointeurs aucune duplication de données n'est nécessaire au lancement du conteneur. ### Empreinte stockage faible * Les images sont peu volumineuses (comparativement à une VM) et idéalement limitées au seul code applicatif et librairies nécessaires. * Les images sont composées de couches superposées qui permettent la gestion des deltas de façon différentielle (FS de type *Union*). * Des conteneurs partageant les mêmes couches d'une image n'ont pas besoin de les dupliquer (technique du Copy-on-Write). ### Déployable partout * Sur n'importe quel système Linux de même architecture, du cloud à la machine locale. * Pas de problème d'incompatibilité de formats d'images (OCI) comme avec les VMs. ### Hybrid et Multi-Cloud ready * Une fois conteneurisées, les applications sont déployables sur n'importe quelle infrastructure : * machines virtuelles, * bare metal, * cloud public et privés quelque soit la technologie d'hyperviseur sous-jacente. ### Microservices * Docker facilite la mise en place d'applications orientées microservices. ![Architecture microservices](images/micro-services.png) [https://docs.microsoft.com/](https://docs.microsoft.com/fr-fr/dotnet/standard/microservices-architecture/architect-microservice-container-applications/media/image6.png) * Chacun des composants de l'application (base de données, serveur web, api, ...) peut être : - exécuté dans son propre conteneur, - mis à jour séparément des autres, - mis à l'échelle séparément des autres. ### Agilité * Les conteneurs permettent un fonctionnement plus agile que les VMs - Construction automatique, - Déploiement rapide, - Immutabilité, - Patching simplifié, - Exécutables via scripts. ## Quelques inconvénients des conteneurs Docker ### Kernel specific * La technologie Docker reposent sur des mécanismes spécifiques au noyau de l'OS. - Les conteneurs applicatifs Linux ne peuvent donc être exécutés que sur des systèmes Linux. - Les conteneurs applicatifs Windows ne peuvent donc être exécutés que sur des systèmes Windows. ### Architecture specific * Les conteneurs ne peuvent être exécutés que sur des systèmes hôtes de même architecture processeur (x86, amd64, arm). ### Sécurité * L'isolation avec des conteneurs est moins forte qu'entre un hyperviseur et ses systèmes invités. * Les risques sont essentiellement liés au partage du kernel entre l'hôte et les conteneurs. * En cas de compromission du kernel, le système entier et tous ses conteneurs doivent être considérés comme compromis. ### Difficultés à conteneuriser * Docker permet d'exécuter pratiquement n'importe quelle application dans un conteneur. * Mais de part leur conception ou leur choix techniques certaines applications peuvent être délicates à conteneuriser. ### Scalabilité complexe * Les conteneurs peuvent être faciles à gérer et utiliser sur une station de travail ou quelques serveurs... * ... mais la scalabilité nécessaire à un environnement de production est un tout autre challenge. * Bon c'était vrai en 2015 ! ## Docker sous Linux ![Docker on Linux](images/docker-on-linux-platform.png) ## Docker sous Windows * A l'origine l'outil _boot2docker_ permettait d'utiliser un hôte Linux minimaliste dans une VM VirtualBox sous Windows. * Le _Docker Runtime_ basé sur la technologie _Windows Containers_ est proposé à partir de _Windows Server 2016_ et autorise pour la première fois la conteneurisation d'applications Windows natives. * Pour faire tourner les applications Linux sur un hôte Windows, une couche de virtualisation reste néanmoins nécessaire. * Les versions légères _core_ et _nano_ de _Windows 2016 Server_ peuvent être utilisées à l'intérieur des conteneurs mais aussi comme hôte Docker. - _core_ est un Windows 2016 Server sans interface graphique. - _nano_ est un Windows 2016 Server réduit au minimum sans interface graphique ni shell intéractif. ![Docker on Windows](images/docker-on-windows-platform.png) ## There is no container! Le _conteneur_ est une notion qui n'existe pas dans le noyau Linux. La conteneurisation est rendue possible par un assemblage de plusieurs technologies inclues dans le Kernel : * namespaces * control groups (cgroups) * secure computing mode (seccomp) * capabilities * linux security modules (lsm) * ulimit ### Ressources systèmes Ces technologies permettent à chaque conteneur de disposer de ses propres ressources systèmes * système de fichiers, * interfaçage réseau, * liste de processus en cours d'exécution, * nom d'hôte, * CPU, * mémoire, * etc. ### namespaces Service fourni par le noyau Linux pour gérer l'_isolation_ des processus : * mount * pid * net * uts * ipc * user * uts (host and domain names) Chaque processus ou groupe de processus est placé dans un namespace. > Les namespaces contrôlent ce qu'un processus peut voir. `$ lsns` ```none NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 82 1931 bob /lib/systemd/systemd --user 4026531836 pid 83 1931 bob /lib/systemd/systemd --user 4026531837 user 75 1931 bob /lib/systemd/systemd --user 4026531838 uts 82 1931 bob /lib/systemd/systemd --user 4026531839 ipc 74 1931 bob /lib/systemd/systemd --user 4026531840 mnt 82 1931 bob /lib/systemd/systemd --user 4026532009 net 74 1931 bob /lib/systemd/systemd --user 4026532436 user 1 10955 bob /home/bob/bin/firefox/firefox-bin -content... 4026532437 ipc 1 10955 bob /home/bob/bin/firefox/firefox-bin -contentproc... 4026532439 net 1 10955 bob /home/bob/bin/firefox/firefox-bin -contentproc... ... ``` Les _namespaces_ fonctionnent par : * _filtrage_ des appels systèmes pour masquer des éléments - par exemple `ps` à l'intérieur d'un conteneur n'affichera que les processus du conteneur * _translation_ pour convertir des éléments - par exemple `ps` à l'intérieur d'un conteneur affichera des PID différents des PID réels #### Le Mount namespace (Linux 2.4.19 - 2002) * Isolation des points de montage du système de fichiers vus par un groupe de processus. * Les points de montage ne sont plus globaux mais spécifiques au namespace. * Racine propre (chroot). #### Le PID namespace (Linux 2.6.24) * Isolation des identifiants de processus (PID). * PID 1 init-like par namespace. * Chaque namespace possède sa propre numérotation PID. * Un processus d'un namespace donné ne peut envoyer de systemcall sur un processus d'un autre PID namespace. * Gestion de pseudo-filesystem (ex : /proc) vu par le PID namespace qui le monte. Un processus possède donc plusieurs PID : un dans le namespace, un en dehors (processus vu par l'hôte). ---- Les processus http vus depuis le conteneur : ```none root@bf7fdbc297bb:~# ps auxfww USER PID %CPU %MEM VSZ RSS STAT START TIME COMMAND root 1 0.0 0.2 77160 4440 Ss+ 11:55 0:00 httpd -DFOREGROUND daemon 7 0.0 0.1 366340 3568 Sl+ 11:55 0:02 \_ httpd -DFOREGROUND daemon 8 0.0 0.1 366340 3568 Sl+ 11:55 0:02 \_ httpd -DFOREGROUND ``` Les processus http vus depuis l'hôte : ```none me@docker-node:~$ ps auxfww USER PID %CPU %MEM VSZ RSS STAT START TIME COMMAND root 1976 0.0 0.2 77160 4440 Ss+ 11:55 0:00 httpd -DFOREGROUND daemon 1984 0.0 0.1 366340 3568 Sl+ 11:55 0:02 \_ httpd -DFOREGROUND daemon 1985 0.0 0.1 366340 3568 Sl+ 11:55 0:02 \_ httpd -DFOREGROUND ``` Il s'agit bien des mêmes processus. #### Le Net namespace (Linux 2.6.19-2.6.24) * Isolation du réseau. * Chaque namespace possède ses propres interfaces, ports, table de routage... * Chaque namespace possède son propre répertoire /proc/net. ### control groups Service fourni par le noyau pour _mesurer_ et _limiter_ les ressources allouées à un groupe de processus. ```none $ ls /sys/fs/cgroup blkio cgmanager cpu cpuacct cpuset devices freezer memory perf_event $ls /sys/fs/cgroup/cpuset/mon-cgroup cgroup.procs cpuset.memory_pressure_enabled notify_on_release cpuset.cpu_exclusive cpuset.memory_spread_page release_agent cpuset.cpus cpuset.memory_spread_slab tasks cpuset.mem_exclusive cpuset.mems cpuset.mem_hardwall cpuset.sched_load_balance $ cat /sys/fs/cgroup/cpuset/mon-cgroup/cpuset.cpus 0-3 ``` control groups == cgroups > Les control groups régulent ce qu'un processus peut utiliser. #### Les cgroups et les conteneurs Docker ```none $ systemd-cgls /docker Control group /docker: ├─ce1aa87edbef6072f56507874cc122642c66d2360741df4a6c1804204574241e │ └─3900 /bin/sh ├─0fe89d4808503f2882480e74df69a45cbb50fe8d523d9e586a48176b0f61f60b │ └─5980 /bin/sh └─dde507e27656f9349574138160aaac0f3a46a99d2d1f0922013e0604c4abbc5f ├─10195 httpd -DFOREGROUND ├─10231 httpd -DFOREGROUND ├─10232 httpd -DFOREGROUND └─10233 httpd -DFOREGROUND ``` ### secure computing mode (seccomp) * Service fourni par le noyau pour _filtrer_ les appels systèmes utilisables par un processus. * Il permet d'attacher à un processus une _liste blanche d'appels systèmes utilisables_, afin d'éviter que ce processus puisse effectuer des opérations jugées dangereuses. * Docker propose par défaut un profil seccomp peu restrictif, mais que l'on peut durcir si besoin. ### capabilities * Service fourni par le noyau pour regrouper des ensembles d'appels systèmes par thématiques. * Par défaut Docker désactive certaines 'capabilités'. ### Linux Security Modules (LSM) * Fonctionnalité du noyau Linux permettant de prendre en charge différents modèles de sécurité. * Les modèles les plus connus sont _SELinux_ et _AppArmor_. * Ces modèles appliquent des restrictions en fonction du contexte. * Docker fourni des profils pour SELinux et AppArmor. ### ulimit * Fonctionnalité du noyau Linux permettant de limiter le nombre de processus utilisable. * Par défaut Docker limite le nombre processus fils dans un conteneur à 512. * Ceci permet d'éviter les fork bomb ! ## Docker Desktop * Sur le poste de travail _Docker Desktop_ propose un environnement Docker près à l'emploi. * Pour Mac et Windows (>2010 Professional ou Enterprise 64-bit). ![Docker Desktop](images/docker-subscription.png) ## Standardisation - __[Container Runtime Interface (CRI)](https://github.com/opencontainers/runtime-spec)__ spécification d'une API commune à tous les moteurs d'exécution de conteneurs. - __[Open Container Initiative (OCI)](https://github.com/opencontainers/image-spec)__ spécifications pour les images et conteneurs. ### Moteurs de Conteneurs compatibles CRI - [containerd](https://containerd.io/) (initié par Docker en 2016) - [cri-o](http://cri-o.io/) (initié par RedHat en 2017) - [Firecracker](https://firecracker-microvm.github.io/) (initié par AWS en 2017) - [Kata Containers](https://katacontainers.io/) (initié par OpenStack en 2017, basé la fusion de Intel Clear Containers et Hyper.sh RunV) - [gVisor](https://gvisor.dev/) (initié par Google en 2018) ### Alternative à Docker : Podman * Gestion de conteneurs via une CLI compatible Docker. * Poussé par RedHat (en standard sur RHEL 8 / Centos 8). * Apporte la fonctionnalité de Pods locaux (notion de base de Kubernetes). * Podman n'utilise pas de daemon (contrairement à Docker). * Podman s'appuie sur systemd pour la surveillance des conteneurs. * Podman utilise les user namespaces pour permettre l'exécution de conteneurs par des utilisateurs non privilégiés. https://k-7.ch/podman-un-moteur-de-conteneur-deamon-less.html ## Opérations de base sur les conteneurs ### Docker CLI ![Cycle de vie Docker](images/docker-cycle.png) ### Docker run Permet d'instancier un conteneur à partir d'une image. `docker run [OPTIONS] IMAGE [COMMAND] [ARG...]` Option | Description - | - `--detach`, `-d` | Mode _détaché_ : lance le conteneur à l'arrière plan `--name NAME` | Donne un nom au conteneur `--interactive`, `-i` | Connexion à l'entrée standard du conteneur `--tty`, `-t` | Nous souhaitons ouvrir un pseudo-terminal Exemple : `docker run --name test debian /bin/cat /etc/resolv.conf` ![Docker run workflow](images/docker-run-workflow.png) ### Lancer un conteneur en mode intéractif ```none $ docker run -ti busybox / # ps -ef PID USER TIME COMMAND 1 root 0:00 sh 7 root 0:00 ps -ef / # ls bin dev etc home proc root sys tmp usr var / # exit ``` * En combinant les options `-t` et `-i` on ouvre une session à l'intérieur du conteneur. * Lorsqu'on quitte le shell, le conteneur est automatiquement arrêté (mais pas détruit). ### Lancer une commande dans un conteneur et récupérer son résultat ```none $ docker run busybox /bin/cat /etc/passwd root:x:0:0:root:/root:/bin/sh daemon:x:1:1:daemon:/usr/sbin:/bin/false bin:x:2:2:bin:/bin:/bin/false sys:x:3:3:sys:/dev:/bin/false sync:x:4:100:sync:/bin:/bin/sync mail:x:8:8:mail:/var/spool/mail:/bin/false www-data:x:33:33:www-data:/var/www:/bin/false operator:x:37:37:Operator:/var:/bin/false nobody:x:99:99:nobody:/home:/bin/false ``` * Ici le conteneur retourne le résultat de la commande sur la sortie standard, rend de suite la main, puis est automatiquement arrêté (mais pas détruit). ### Lancer un conteneur à l'arrière plan ```none $ docker run -d httpd dde507e27656f9349574138160aaac0f3a46a99d2d1f0922013e0604c4abbc5f ``` * Docker retourne l'identifiant du conteneur créé et rend de suite la main. * Le conteneur continue à tourner à l'arrière plan jusqu'à ce que le processus plante ou qu'on l'arrête explicitement. ### Lister les conteneurs `docker ps [OPTIONS]` ```none $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES dde507e27656 httpd "httpd..." 2 seconds ago Up 2 seconds 80/tcp reverent... 0fe89d480850 busybox "/bin/sh" 44 minutes ago Up 42 minutes vigilant... ce1aa87edbef busybox "/bin/sh" About an ho... Up About a... trusting... ``` * Par défaut seuls les conteneurs actuellement en cours d'exécution sont affichés. * L'option `-a` permet d'afficher tous les conteneurs quelque soit leur état. ### Stopper des conteneurs Commande | Description ---------------------------------|--------------------------------------------------------------------------------------------------------------------- `exit` | Ou n'importe quelle autre commande permettant de terminer le processus principal depuis le conteneur `docker stop CONTAINER` | Le processus principal à l'intérieur du conteneur reçoit un SIGTERM, et après un délai de grâce de 10s un SIGKILL `docker kill CONTAINER` | Le processus principal à l'intérieur du conteneur reçoit un SIGKILL ou tout autre signal spécifié avec l'option `-s`
https://medium.com/@gchudnov/trapping-signals-in-docker-containers-7a57fdda7d86 `docker stop $(docker ps -a -q)` | Stoppe tous les conteneurs ### Autres opérations Commande | Description -----------------------------------------|------------------------------------------- `docker start CONTAINER [CONTAINER...]` | Démarre un ou plusieurs conteneurs stoppés `docker restart CONTAINER [CONTAINER...]`| Redémarre un ou plusieurs conteneurs `docker rm CONTAINER [CONTAINER...]` | Supprime un ou plusieurs conteneurs `docker container prune` | Supprime tous les conteneurs `docker pause CONTAINER` | Suspend le conteneur ### Docker logs Afficher les logs d'un conteneur. `docker logs -f mon_conteneur` Option | Description - | - `--details` | Affiche des détails supplémentaires `--follow`, `-f` | Continue à afficher les logs de manière intéractive `--since` | Affiche les logs à partir d'une certaine date `--tail` | Affiche les `n` dernières lignes `--timestamps`, `-t` | Affiche les timestamps Par défaut, `docker logs` affiche la sortie d'une commande jouée à l'intérieur du conteneur exactement comme elle apparaîtrait si on la jouait interactivement dans un terminal. Les commandes Linux ouvrent généralement 3 flux I/O : `STDIN`, `STDOUT`, and `STDERR`. Flux | Description - | - `STDIN` | Flux d'entrée de la commande (ex: clavier, sortie d'une autre commande...) `STDOUT`| Flux de sortie pour les messages 'normaux' de la commande `STDERR`| Flux de sortie pour les messages d'erreur de la commande Par défaut `docker logs` affiche les flux `STDOUT` et `STDERR` de la commande jouée à l'intérieur du conteneur. ### Logging drivers Driver | Description - | - `none` | Aucune gestion de logs pour le conteneur. `json-file` | Les logs sont formatés en `JSON`. C'est le choix par défaut. `syslog` | Ecrit les logs dans syslog (Le démon syslog doit tourner sur la machine hôte). `journald` | Ecrit les logs dans journald (Le démon journald doit tourner sur la machine hôte). `gelf` | Ecrit les logs au format Graylog Extended Log Format, en vue d'un traitement par Graylog ou Logstash. ... | Y'en a d'autres ! Actuellement, seuls les drivers `json-file` et `journald` sont exploitables via la commande `docker logs`. ### Logging - bonnes pratiques * https://success.docker.com/article/logging-best-practices * https://docs.docker.com/config/containers/logging/configure/ ### Docker derrière un proxy #### Configuration du Docker-Engine Pour forcer le docker-engine à utiliser un proxy : `/etc/systemd/system/` `docker.service.d/http-proxy.conf` ``` [Service] Environment="HTTP_PROXY=http://proxy.example.com:3128/" Environment="HTTPS_PROXY=http://proxy.example.com:3128/" ``` ``` systemctl daemon-reload systemctl restart docker.service ``` ## Travaux pratiques ![Travaux pratiques](images/tp.gif) [TP Docker Introduction](../travaux-pratiques/slides/docker/tp-docker-introduction.html) ## Docker Network Comment fonctionne le réseau avec Docker ? ### Lister les réseaux existants `docker network ls` ```none $ docker network ls NETWORK ID NAME DRIVER SCOPE b69de2fd946f bridge bridge local 90d83d01c5cd formation bridge local e59c9b6ccc29 host host local e15666fbca66 none null local ``` (+ le driver `container` !) ### Réseau none * Un conteneur démarré sur le réseau `none` utilisant le driver `null` sera complètement isolé. * Seule l'interface loopback sera disponible dans le conteneur. * Idéal pour des conteneurs de calculs qui n'ont besoin d'aucun accès à des ressources externes. ```none $ docker run --net=none -ti busybox ``` ```none / # ip a 1: lo: mtu 65536 qdisc noqueue qlen 1 inet 127.0.0.1/8 scope host lo ``` ### Réseau host * Un conteneur démarré sur le réseau `host` se trouvera dans le même namespace réseau que l'hôte lui-même. * Le conteneur pourra donc utiliser directement la stack réseau de l'hôte. * Performances natives. (pas de NAT, de bridge ni de veth) ```none $ docker run --net=host -ti busybox ``` ```none / # ip a 1: lo: mtu 65536 qdisc noqueue qlen 1 inet 127.0.0.1/8 scope host lo 2: enp10s0: mtu 1500 qdisc... inet 10.6.208.11/24 brd 10.6.208.255 scope global dynamic... 3: ... ``` ### Réseau host ![Réseau Host](images/docker-networking-host.jpg) Attention aux conflits dans l'utilisation des ports réseaux. ### Réseau container * Un conteneur démarré en utilisant le driver `container` se trouvera dans le même namespace réseau que l'autre conteneur spécifié. * Les deux conteneurs partageront les mêmes interfaces réseaux, réseaux, règles iptables, etc... * Il pourront communiquer entre eux en utilisant l'interface loopback. ### Réseau container ```none docker run -ti --name c1 busybox / # ip a 1: lo: mtu 65536 qdisc noqueue qlen 1 inet 127.0.0.1/8 scope host lo 1077: eth0@if1078: mtu... inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 ``` ```none $ docker run -ti --name c2 --net container:c1 busybox / # ip a 1: lo: mtu 65536 qdisc noqueue qlen 1 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 1077: eth0@if1078: mtu... inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 ``` Ici les conteneurs `c1` et `c2` partagent les mêmes interfaces réseau (`lo` et `eth0`). ### Réseau Bridge * Par défaut les conteneurs sont démarrés sur le réseau Docker interne `bridge` nommé `docker0`. * Ces conteneurs n'exposent aucune connectivité au monde externe mais peuvent communiquer entre eux à la condition qu'ils soient placés sur le même hôte. ```none $ docker run -ti busybox ``` ```none / # ip a 1: lo: mtu 65536 qdisc noqueue qlen 1 inet 127.0.0.1/8 scope host lo 13: eth0@if14: mtu... inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 ``` #### Bridge - Schéma ![Docker Network](images/network.jpg) #### Bridge - Fonctionnement * Les adresses sont allouées par défaut sur le subnet interne `172.17.0.0/16` (configurable avec `--bip`). * Le trafic sortant passe par une règle iptables MASQUERADE. * le trafic entrant passe par une règle iptables DNAT. #### Bridge - Exposition de ports * Pour exposer un port au niveau du conteneur, on peut ajouter l'option `--expose` qui permet de surcharger la directive `EXPOSE` d'un Dockerfile. * Ceci permet d'attaquer le service à partir de l'adresse IP du conteneur. ![Expose](images/network-expose.png) ### Bridge - Mapping de ports * Pour publier un port au niveau de l'hôte on peut ajouter l'option `--publish` qui permet de mapper un port déjà exposé sur le conteneur vers l'hôte. * On le formate de la manière : `--publish HOST-PORT:CONTAINER-PORT` * Avec `--publish-all` on ouvre tout les ports exposés d'un conteneur (ce n'est pas forcément conseillé). ![Expose](images/network-expose-publish.png) #### Exemple ```none $ docker run -d --name web --publish 8000:5000 httpd:2.4 ``` On ouvre le port 8000 de l'hôte et on le mappe au port 5000 de notre conteneur. ### Commande network 1. Créer un réseau bridge `$ docker network create --driver bridge NETWORK` 2. Afficher les détails d'un réseau `$ docker network inspect NETWORK` 3. Supprimer un réseau existant `$ docker network rm NETWORK` 4. Attacher un réseau existant à un conteneur existant `$ docker network connect NETWORK CONTAINER` ### Docker DNS embarqué - Sur le réseau bridge par défaut, il n'est pas possible de résoudre les adresses IP des conteneurs depuis leurs noms. - Il faut pour ça créer un réseau personalisé. - Ainsi, tous les conteneurs démarrés sur ce réseau vont pouvoir communiquer entre eux grâce à leurs noms. - Le fichier _/etc/resolv.conf_ du conteneur est automatiquement alimenté avec _nameserver 127.0.0.11_. ### Exemple * Ajout d'un nouveau réseau de type Bridge : ```none $ docker network create --driver bridge mon-reseau ``` * Démarrage d'un conteneur sur le nouveau réseau avec l'option `--network` : ```none $ docker run --detach --name apache --publish 8080:80 \ --network mon-reseau httpd:2.4 ``` Si on ajoute d'autres conteneurs sur ce réseau, il pourront communiquer entre eux directement en utilisant le nom attribué avec l'option `--name`. ### Plus de détails sur les réseaux Docker * https://success.docker.com/article/networking ## Travaux pratiques ![Travaux pratiques](images/tp.gif) [TP Network](../travaux-pratiques/slides/docker/tp-network.html)