Resources attached to the Road To DevOps tutorial https://blog.noobtoroot.xyz/road-to-devops/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

19 KiB

Docker

Schema Docker Swarm

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 :

    1. lance une Out Of Memory Exception (OOME),

    2. 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.

ctop

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

Travaux pratiques

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

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.

Type de montage

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

Type de montage

  • 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>/).

  1. Créer un volume
    $ docker volume create VOLUME

  2. Lister les volumes
    $ docker volume ls

  3. Inspecter un volume
    $ docker volume inspect VOLUME

  4. Supprimer un volume
    $ docker volume rm VOLUME

  5. 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

Type de montage

  • 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

Type de montage

  • 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

  1. Monte un volume nommé
    $ docker run --detach \
      --name apache \
      --publish 8080:80 \
      --mount source=mon-volume,target=/var/www/mon-app \
      httpd:2.4
  1. 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
  1. 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

Travaux pratiques

TP Docker Volumes

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
  • Supprime les volumes orphelins

  • Supprime les réseaux vides

Travaux pratiques

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

Travaux pratiques

TP Docker Compose

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 !!