# 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)