19 KiB
Docker
Les conteneurs - Utilisation avancée
Maxime Poullain • Christian Tritten
Docker run
Permet d'instancier un conteneur à partir d'une image
Docker run - options
Option | Description
-
| -
--detach
, -d
| Mode détaché : lance le conteneur à l'arrière plan
--name NAME
| Donne un nom au conteneur
--interactive
, -i
| Conserve STDIN ouvert
--tty
, -t
| Alloue un pseudo-TTY
Docker run - restart policies
On utilise l'option --restart
avec ces paramètres :
Policy | Result |
---|---|
no |
Par défaut. Ne redémarre pas |
on-failure[:max-retries] |
Redémarre seulement avec un non-zero exit status |
always |
Redémarre tout le temps et indéfiniment. Démarre aussi en même temps que le démon Docker |
unless-stopped |
Redémarre tout le temps sauf si il a été coupé |
Contraintes sur les ressources
-
Par défaut une application conteneurisée peut consommer l'intégralité de la mémoire disponible de l'hôte.
-
Lorsqu'il n'y a plus de mémoire disponible, le kernel Linux :
-
lance une Out Of Memory Exception (OOME),
-
commence à tuer des processus pour libérer de la mémoire.
-
Il est possible de limiter les ressources allouées à un conteneur grâce à la technologie des control groups.
Option | Description |
---|---|
--memory |
Limite mémoire, minimum 4M |
--memory-swap |
Limite mémoire totale, (memoire + swap) |
--cpu |
Limite sur l'utilisation du cpu |
https://docs.docker.com/config/containers/resource_constraints/
Sur un système en production il est recommandé d'appliquer systématiquement des limitations sur l'utilisation de la mémoire.
Docker exec
Permet d'éxécuter des commandes dans le conteneur en plus du processus de base.
Notamment utile pour débugger.
Docker exec - options
Option | Shorthand | Default | Description |
---|---|---|---|
--detach |
-d |
False | Detached mode: run command in the background |
--interactive |
-i |
False | Keep STDIN open even if not attached |
--tty |
-t |
False | Allocate a pseudo-TTY |
--user |
-u |
False | Username or UID |
Docker exec - exemple
-
Ouvrir une console Bash dans le conteneur :
$ docker exec -it mon_conteneur /bin/bash
-
Créer un fichier à l'intérieur du conteneur :
$ docker exec mon_conteneur touch /tmp/test
Docker cp
Permet de copier des fichiers/dossiers depuis et vers un conteneur en cours d'exécution.
-
Copie un fichier de l'hôte vers le conteneur :
$ docker cp fichier nom-du-conteneur:/chemin/vers/fichier
-
Créer un fichier du conteneur vers l'hôte :
$ docker cp nom-du-conteneur:/chemin/vers/fichier fichier
Docker diff
Affiche les modifications effectuées sur le système de fichiers du conteneur.
$ docker diff mon-conteneur
C /var
C /var/lib
C /var/lib/apt
C /var/lib/apt/lists
A /var/lib/apt/lists/lock
A /var/lib/apt/lists/auxfiles
A /var/lib/apt/lists/deb.debian.org_debian_dists_bullseye_InRelease
A /var/lib/apt/lists/partial
Monitoring simple des conteneurs
Docker Stats
Docker embarque un équivalent de la commande top
permettant d'afficher les métriques des conteneurs en cours d'exécution.
docker stats
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
5098617c3654 0.05% 0B / 0B 0.00% 648B / 0B 0B / 0B 2
b2d0efcb5151 1.00% 0B / 0B 0.00% 648B / 0B 0B / 0B 3
cbdb1069b241 0.10% 0B / 0B 0.00% 648B / 0B 0B / 0B 5
ctop
Métriques des conteneurs dans une interface à la top
.
Source : https://ctop.sh/
Configuration d'une application
Variables d'environnement
-
Il est possible d'injecter des variables d'environnement dans le conteneur au moment de sa création.
-
L'option
--env
permet de spécifier une variable et sa valeur. -
L'option
--env-file
permet de passer un fichier de variables. -
Une fois injectées dans le conteneur ces variables sont accessibles par le premier processus lancé.
Exemple
-
L'image de MariaDB est conçue pour être configurée à l'exécution à l'aide de variables d'environnement.
-
Ces variables vont permettre d'initialiser une base avec un utilisateur et mot de passe personnalisés.
$ docker run --name mariadb \
--env MYSQL_ROOT_PASSWORD=docker \
--env MYSQL_DATABASE=docker \
--env MYSQL_USER=docker \
--env MYSQL_PASSWORD=docker \
mariadb:10.7.1
Exemple avec --env-file
mariadb-vars
MYSQL_ROOT_PASSWORD=docker
MYSQL_DATABASE=docker
MYSQL_USER=docker
MYSQL_PASSWORD=docker
$ docker run --name mariadb \
--env-file=mariadb-vars \
mariadb:10.7.1
Mini TP : variables d'environnement
Créer un conteneur basé sur l'image xian310/who-is-there:21
avec la configuration suivante :
-
Lancer le conteneur au premier plan.
-
Publier le port d'écoute dans le conteneur (8080) vers le port de votre choix sur l'hôte.
Accéder à l'application dans le navigateur web en précisant le chemin /env
dans l'url.
Créer le conteneur :
$ docker run --rm --publish 8080:8080 xian310/who-is-there:21
Accéder à l'application :
$ firefox http://127.0.0.1:8080/env
-
Supprimer le conteneur.
-
Créer un nouveau conteneur en lui passant au moins 2 variables d'environnement de votre choix.
-
Recharger la page web.
Créer un nouveau conteneur en lui passant des variables d'environnement :
$ docker run --rm --publish 8080:8080 \
--env MA_VARIABLE=hello --env MON_AUTRE_VARIABLE="au revoir" \
xian310/who-is-there:21
-
On peut configurer la couleur de fond de la page
/env
en passant la variableCOLOR
au conteneur. -
Pour une liste des couleur possibles :
https://fr.wikipedia.org/wiki/Couleur_du_Web
Changer la couleur de fond de la page /env
:
$ docker run --rm --publish 8080:8080 \
--env COLOR=lightblue \
xian310/who-is-there:21
$ docker run --rm --publish 8080:8080 \
--env COLOR=pink \
xian310/who-is-there:21
Gestion des données
Persistance des données avec Docker
3 mécanismes différents
Docker offre trois mécanismes permettant de monter des données de l'hôte dans un conteneur :
-
volumes
-
bind mounts
-
tmpfs volumes
Dans le doute les volumes sont presque toujours le bon choix.
Source : documentation officielle Docker
Quel que soit le type de montage utilisé, les données seront présentées de la même façon au conteneur, c'est à dire sous la forme d'un dossier ou d'un fichier unique.
Volumes
-
Les volumes sont stockés sur le système de fichiers de l'hôte dans le dossier
/var/lib/docker/volumes/
. -
Un volume est créé et managé par Docker.
-
Les processus autres que Docker ne devraient donc pas y modifier directement les données.
-
Un volume peut être monté simultanément dans plusieurs conteneurs
-
en lecture/écriture ou lecture seule,
-
très utile pour partager des données entre conteneurs.
-
-
Un volume est indépendant des conteneurs.
-
Le contenu persiste même si aucun conteneur n'utilise le volume.
-
Un volume doit être explicitement supprimé.
-
un volume peut être nommé ou anonyme.
(Un volume anonyme se voit attribuer un identifiant unique sur l'hôte) -
Les volumes supportent la notion de volume drivers. (pour stocker les données sur des hôtes distant ou dans le cloud par exemple)
-
un volume peut être sauvegardé, restoré ou migré facilement d'un hôte Docker à l'autre.
(Stopper les conteneurs utilisant le volume, sauvegarder le dossier/var/lib/docker/volumes/<volume-name>/
).
-
Créer un volume
$ docker volume create VOLUME
-
Lister les volumes
$ docker volume ls
-
Inspecter un volume
$ docker volume inspect VOLUME
-
Supprimer un volume
$ docker volume rm VOLUME
-
Supprimer tous les volumes non-utilisés
$ docker volume prune
$ docker volume create mon-volume
$ docker volume inspect mon-volume
[
{
"CreatedAt": "2018-01-16T10:15:51+01:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/mon-volume/_data",
"Name": "mon-volume",
"Options": {},
"Scope": "local"
}
]
docker volume inspect
permet de connaître le chemin réel du volume sur le système hôte.
Bind mounts
-
Les bind mounts permettent de "monter" n'importe quel fichier ou dossier du système hôte à l'intérieur du conteneur.
-
Exemples d'utilisation de Bind mount :
-
partager des fichiers de configuration entre l'hôte et des conteneurs.
-
partager du code source entre l'hôte et un conteneur (sur un poste de développement).
-
-
Le fichier ou le répertoire source peut ne pas exister au préalable sur l'hôte (il sera créé le cas échéant).
-
Attention !
Si un dossier ou fichier critique pour le système hôte est monté dans le conteneur, ce dernier peut y accéder sans restriction.
tmpfs mounts
-
Les tmpfs mounts sont stockés directement dans la mémoire de l'hôte.
-
Les données sont donc volatiles et détruites en même temps que le conteneur qui les utilise (ou en cas de reboot du système).
-
Les tmpfs mounts ne peuvent pas être partagés entre plusieurs conteneurs.
Exemples de montages
- Monte un volume nommé
$ docker run --detach \
--name apache \
--publish 8080:80 \
--mount source=mon-volume,target=/var/www/mon-app \
httpd:2.4
- Monte un répertoire local (bind mount)
$ docker run --detach \
--name apache \
--publish 8080:80 \
--mount type=bind,source=/home/debian/mon-app,destination=/var/www/mon-app \
httpd:2.4
- Monte un répertoire local (bind mount) en read-only
$ docker run --detach \
--name apache \
--publish 8080:80 \
--mount type=bind,source=/home/debian/mon-app,destination=/var/www/mon-app,readonly \
httpd:2.4
-v ou --mount ?
-
A l'origine , les options
-v
et--volume
étaient utilisées pour les conteneurs standalone et l'option--mount
pour les services Swarm. -
On peut utiliser les 2 syntaxes.
Volumes et droits d'accès
Attention : les accès sur les fichiers
restent soumis aux droits Linux.
Travaux pratiques
Accéder à la racine du système de fichiers du conteneur
# docker inspect -f '{{.State.Pid}}' mon-conteneur
11384
# cd /proc/11384/root/
total 52
drwxr-xr-x 19 root root 4096 déc. 18 17:26 ./
drwxr-xr-x 19 root root 4096 déc. 18 17:26 ../
drwxr-xr-x 2 root root 12288 mars 9 2017 bin/
drwxr-xr-x 5 root root 360 déc. 18 17:08 dev/
-rwxr-xr-x 1 root root 0 déc. 18 17:08 .dockerenv*
drwxr-xr-x 2 root root 4096 déc. 18 17:08 etc/
drwxr-xr-x 2 99 99 4096 mars 9 2017 home/
dr-xr-xr-x 263 root root 0 déc. 18 17:08 proc/
drwxr-xr-x 2 root root 4096 déc. 18 17:23 root/
dr-xr-xr-x 13 root root 0 déc. 18 17:11 sys/
drwxrwxrwt 2 root root 4096 mars 9 2017 tmp/
drwxr-xr-x 3 root root 4096 mars 9 2017 usr/
drwxr-xr-x 4 root root 4096 mars 9 2017 var/
Spécification RunC : https://github.com/opencontainers/runc/blob/master/libcontainer/SPEC.md
Connaître l'espace disque utilisé par Docker
docker system df
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 23 2 3.871GB 3.794GB (98%)
Containers 11 0 2.989GB 2.989GB (100%)
Local Volumes 4 0 94.22MB 94.22MB (100%)
Nettoyer le système
docker system prune
-
Supprime les conteneurs arrêtés
-
Supprimes les images qui n'ont plus de tag associé
- avec
-a
supprime aussi les images non utilisées
- avec
-
Supprime les volumes orphelins
-
Supprime les réseaux vides
Travaux pratiques
TP application complète Web + DB
Docker Compose
Application multi-conteneurs
-
Compose est un outil permettant de configurer et déployer une application composée de plusieurs conteneurs.
-
Compose n'est pas inclus dans Docker il faut donc l'installer en plus.
https://docs.docker.com/compose/
-
L'application (mono-conteneur ou multi-conteneurs) est décrite dans un fichier texte au format yml.
-
Chaque service (conteneur) possède sa propre section de configuration.
-
Par défaut un réseau personnalisé de type Bridge est automatiquement créé pour que l'ensemble des conteneurs de l'application :
-
puissent communiquer entre eux,
-
être isolés des autres conteneurs.
-
docker-compose.yml
version: '3'
services:
web:
build: . # ici l'image sera construite à partir d'un Dockerfile
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
redis:
image: redis # ici on reprend une image déjà existante
volumes:
logvolume01: {}
Directive | Description |
---|---|
image |
Spécifie l'image Docker à utiliser |
build |
Spécifie le chemin pour build l'image |
ports |
Configure la publication de ports |
depends_on |
Exprime la dépendance entre plusieurs services et ainsi l'ordre de lancement |
restart |
Spécifie le configuration de redémarrage du conteneur |
healthcheck |
Configure une vérification de la santé du service |
... |
https://docs.docker.com/compose/compose-file/ |
Derrière un proxy :
version: "3"
services:
my-service:
build:
context: my-folder/
args:
- http_proxy=http:///my.proxy.url:3128
- https_proxy=https:///my.proxy.url:3128
Pour vérifier la syntaxe du fichier docker-compose.yml :
$ docker-compose config
Pour déployer la stack applicative
en une seule commande :
$ docker-compose up -d
Pour arrêter la stack sans supprimer les conteneurs :
$ docker-compose stop
Pour supprimer complètement la stack :
$ docker-compose down
Cela entraîne la suppression des conteneurs et des réseaux associés.
Pour afficher les logs
de tous les conteneurs de la stack :
$ docker-compose logs
Le fichier .env
-
Permet de déclarer des variables dont la valeur sera automatiquement substituée lors du traitement du fichier docker-compose.yml.
-
Est localisé dans le même dossier que docker-compose.yml.
-
docker-compose config
permet de visualiser le fichier final.
.env
MA_VARIABLE=hello-world
MON_AUTRE_VARIABLE=bonjour
docker-compose.yml
version: '3'
services:
hello:
image: ${MA_VARIABLE}
environment:
- env_var_name=${MON_AUTRE_VARIABLE}
Travaux pratiques
Docker CMD --format
Permet d'utiliser des templates Go pour personnaliser l'affichage
$ docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID REPOSITORY TAG
1afc387274f5 cheatsheet latest
258031686918 node 8.1.2
a2ff708b7413 debian latest
00f017a8c2a6 busybox latest
00f017a8c2a6 10.6.30.30:5000/mpoullain/busybox latest
https://docs.docker.com/engine/admin/formatting/
API du démon Docker
-
Le démon Docker fourni une API qui permet de :
-
récupérer des informations sur le démon et les objets Docker
-
lancer des commandes
-
-
Documentation : https://docs.docker.com/develop/sdk/
Lister les conteneurs :
$ curl --unix-socket /var/run/docker.sock http://1.24/containers/json | jq .
[
{
"Id": "4ab7c5898ac9a594b42406c0afc2250b1b7da36e8966348c09e32fde84515608",
"Names": [
"/determined_bohr"
],
"Image": "debian:stretch",
"ImageID": "sha256:8626492fecd368469e92258dfcafe055f636c21a5865a98a0a6...",
"Command": "bash"
}
...
]
Démarrer un conteneur :
$ curl --unix-socket /var/run/docker.sock -X POST \
http://1.24/containers/4ab7c5898ac9/start
Afficher les logs d'un conteneur :
$ curl --unix-socket /var/run/docker.sock \
http://1.24/containers/4ab7c5898ac9/logs?stdout=1
Mode debug
Il est possible d'activer le mode debug
du démon Docker :
root@node1: # sudo cat /etc/docker/daemon.json
{"debug":true}
root@node1: # systemctl reload docker
root@node1: # tail -f /var/log/syslog
c'est beaucoup plus verbeux !!