Docker Engine

Prise en main

Historique de la présentation

  • ENSG, février 2017
  • IGN, avril et mai 2018
  • ENSG, février 2018
  • ENSG, novembre 2018
  • ENSG, octobre 2019

Moi

Thibault Coupin

  • §fragment Ingé Sys DevOps à l’IRD
  • §fragment Anciennement Chef division WebServices & DevOps au Géoportail
  • §fragment thibault.coupingmail.com
  • §fragment tcoupin
  • §fragment @thibbojunior

Ce cours est :

  • super intéressant
  • open-source sous licence GNU GPL
  • disponible sur
  • propulsé fièrement par reveal.js via Gh-reveal

Sommaire

§id:sommaire§;

Intro

§id:intro§;

C’est quoi la virtualisation ?

Simuler un système “invité” sur un système “hôte”.

On simule le disque dur, la carte mère, les processeurs…§fragment

C’est un peu lourd §fragment

C’est quoi la para-virtualisation ?

Limiter la simulation logiciel du matériel, en simulant un matériel similaire au matériel réel et passer directement les instructions au matériel.

C’est un peu moins lourd §fragment

C’est pas encore ça …

$ ps aux 
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  30108  5812 ?        Ss   15:26   0:02 /sbin/init
root         2  0.0  0.0      0     0 ?        S    15:26   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    15:26   0:00 [ksoftirqd/0]
root         5  0.0  0.0      0     0 ?        S<   15:26   0:00 [kworker/0:0H]
root         7  0.0  0.0      0     0 ?        S    15:26   0:05 [rcu_sched]
root         8  0.0  0.0      0     0 ?        S    15:26   0:00 [rcu_bh]
root         9  0.0  0.0      0     0 ?        S    15:26   0:00 [migration/0]
root        12  0.0  0.0      0     0 ?        S    15:26   0:00 [migration/1]
root        13  0.0  0.0      0     0 ?        S    15:26   0:00 [ksoftirqd/1]
...

Environ 200 processus actifs…

ça fait beaucoup pour une seule application utile.

Comment c’est avec docker ?

Docker ne lance qu’un seule processus, c’est plus simple !§fragment

$ docker run --rm alpine ps aux
PID   USER     TIME   COMMAND
    1 root       0:00 ps aux
§fragment

Qu’est ce que c’est ?

Docker Engine est un outil permettant l’exécution d’application packagée de façon isolée, on parle de conteneur.

Qu’est ce que c’est ?

  • Un système d’isolation de processus, de système de fichier et de réseau : on peut exécuter des processus comme s’ils étaient tout seuls et contrôler ce qu’ils voient§fragment.§fragment
  • Un système d’image pour facilement transporter une application et ses dépendances : un super “zip”.§fragment§fragment

Presque comme la virtualisation, mais non.

Petit historique

  • 2008 : dotCloud, Inc., société française de PaaS, développe Docker
  • mars 2013 : Docker open source, c’est la nouvelle tendance
  • octobre 2013 : dotCloud, Inc. devient Docker, Inc. basé à San Francisco
  • 2015 : docker for Mac et docker for Windows
  • 2016 : orchestration multi-hôte intégrée avec SwarmMode
  • 2018 : Kubernetes devient officiellement une solution de clustering certifiée Docker

Terminologie : les 4 éléments

Pour démarrer une application de façon isolée, on lance un conteneur§fragment basé sur une image§fragment.

Pour stocker des données on peut associer le conteneur à un ou plusieurs volumes§fragment.§fragment

Le conteneur peut être associé à un ou plusieurs réseaux§fragment pour communiquer avec d’autres conteneurs ou avec l’extérieur.§fragment

Architecture

Docker Engine est composée de 2 éléments principaux :

  • le daemon §fragment: c’est lui qui gère les conteneurs et les à-côtés, il expose une API
  • le cli §fragment: la ligne de commande qui contrôle le daemon via son API

Les variantes

Docker Engine est disponible en 2 variantes :

  • CE : community edition, version gratuite que nous allons utiliser ;
  • EE : entreprise edition, plus évoluée avec des fonctionnalités supplémentaires et une certification de fonctionnement sur certain matériel.

Les versions

Depuis mars 2017, AA.MM avec AA l’année et MM le mois (ex. : 17.04 pour la version d’avril 2017)

  • une version stable est compilée tous les trimestre (ex : 17.03, 17.06, 17.09, 17.12…) ;
  • une version edge est compilée tous les mois et contient les nouvelles fonctionnalitées.

La ligne de commande

La suite de cette présentation aborde les concepts de docker et liste les commandes utiles.

La liste complète est disponible :

Dans les versions actuelles, 2 API cohabitent. On ne parlera que de la plus récente.

En pratique

Pour tester les exemples de commandes qui suivent, il faut :

Retour sommaire

Les images

§id:images§;

L’image est le “disque dur”* figée sur lequel va se baser le conteneur.

Elle contient le système d’exploitation, l’application et des métadonnées.

*Le terme “disque dur” n’est pas parfait, à voir juste après dans le chapitre conteneurs

Où trouve-t-on les images ?

  • Sur des registry sur internet, principalement hub.docker.com
  • sur votre serveur si vous avez déjà télécharger l’image

Images personnalisées

  • à construire soi-même
    • from sracth ou basée sur des images de base (ubuntu, centOs, alpine)
    • à partir d’un Dockerfile
    • en commitant un conteneur

Les commandes utiles

Transfert des images

# Authentification
docker login
# Télécharger une image
docker image pull REGISTRY/IMAGE:TAG
# Téléverser une image
docker image push REGISTRY/IMAGE:TAG

Les commandes utiles

Lister les images locales

$ docker image ls
REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE
forumi0721/alpine-armv7h-minidlna   latest              8418d491e218        2 weeks ago         44.34 MB
traefik                             latest              a1350c91b51e        3 weeks ago         37.91 MB
portainer/portainer                 arm                 dc7e0ee82da9        6 weeks ago         10.27 MB
tcoupin/rpi-gpass                   latest              f8bfd0e5c152        6 weeks ago         193.8 MB
...

Supprimer une image locale

$ docker image rm REGISTRY/IMAGE:TAG

Les commandes utiles

Renommer/retagguer une image

$ docker image tag REGISTRY/IMAGE:TAG REGISTRY/IMAGE:TAG

Les commandes utiles

Construire une image avec un Dockerfile

$ docker image build -t REGISTRY/IMAGE:TAG DOCKERFILE_PATH
  • DOCKERFILE_PATH est le chemin du dossier contenant le Dockerfile.

Plus de détails dans le chapitre Dockerfile.

Les commandes utiles

Voir les métadonnées d’une image

$ docker image inspect REGISTRY/IMAGE:TAG

Beaucoup de chose !§fragment

Retour sommaire

Les conteneurs

§id:containers§;

  • Un conteneur est une instance d’image.
  • Le conteneur permet d’isoler un processus (et ses enfants)
  • Le conteneur ne peut pas vivre si le processus se termine.
  • Chaque conteneur a son propre stockage même s’ils sont basés sur la même image.

Démarrer un conteneur

$ docker container run OPTIONS REGISTRY/IMAGE:TAG COMMANDE 
  • OPTIONS : diverses options sont possibles
  • REGISTRY/IMAGE:TAG : le nom de l’image ou son identifiant. On peut préciser une version avec le TAG
  • COMMANDE : la commande à lancer dans le conteneur. L’image peut être associée à une commande par défaut

Démarrer un conteneur

Exemple :

$ docker container run debian:jessie cat /etc/hostname

Le conteneur affiche le contenu du fichier /etc/hostname et s’arrête.

Démarrer un conteneur

Exemple :

$ docker container run -it debian:jessie /bin/bash

Démarre un terminal bash dans le conteneur.

Comme si on était dans une VM.

Lister les conteneurs

$ docker container ls
CONTAINER ID        IMAGE                               COMMAND                  CREATED             STATUS              PORTS                                      NAMES

Mais pourquoi on ne voit pas les conteneurs d’avant ? §fragment

$ docker container ls -a §fragment
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS                     PORTS                               NAMES
a5b74e24da65        debian:jessie            "cat /etc/hostname"      9 seconds ago       Exited (0) 6 seconds ago                                       happy_cori

L’activité des conteneurs

$ docker container stats [NOM]

Supprimer les conteneurs

$ docker container rm NOM

Gérer les conteneurs

  • stop et start (kill aussi)
  • restart
  • pause et unpause

Options utiles

  • –name : donner un nom au conteneur§fragment
  • -i : interactif§fragment
  • -t : forcer l’allocation d’un TTY§fragment
  • –rm : supprimer le conteneur à la fin de son exécution§fragment
  • -d : démarrer le conteneur en arrière-plan§fragment

Il en existe beaucoup d’autres : gestion des ressources, environnement d’exécution…§fragment

Le stockage dans un conteneur

Les modifications dans le système de fichier sont stockées dans une surcouche de l’image.

Couches de conteneurs §pelement:style=max-height:35vh§;

Retour sommaire

Les réseaux

§id:networks§;

L’isolation porte aussi sur le réseau.

  • On contrôle les liens réseaux associés au conteneur : réseaux virtuels§fragment §fragment
  • On contrôle les liens entre ces réseaux virtuels et les réseaux physiques de l’hôte.§fragment

L’option --net

La commande run offre l’option --net

Les 4 valeurs :

  • none : pas de réseau
  • host : les réseaux de l’hôte
  • bridge (par défaut) : un réseau isolé avec un mécanisme de bridge
  • Le nom d’un réseau créé avec la commande docker network create

Pas de réseau

$ docker container run --rm --net none debian:jessie ip a

Seulement l’interface loopback.§fragment

Réseau de l’hôte

$ docker container run --rm --net host debian:jessie ip a

Toutes les interfaces de la machine hôte (eth0, wlan0…).§fragment

Réseau isolé

  • Les conteneurs sont sur un réseau séparé
  • Ils peuvent communiquer avec l’extérieur et entre eux (via l’IP)
  • L’extérieur ne peut pas communiquer avec le conteneur, sauf si explicitement demandé (option -p).

Réseau créé

  • Prévu pour interconnecter des conteneurs
  • Même fonction que bridge + résolution DNS des autres conteneurs

Exposer un port avec l’option -p

$ docker container run --rm -p 8080:80 httpd:alpine

http://127.0.0.1:8080

Le port 8080 de la machine hôte est redirigé vers le port 80 du conteneur.§fragment

Création de réseaux

On peut gérer plus finement les réseaux avec des commandes :

$ docker network create ...
$ docker network connect ...
$ docker network ls ...
$ docker network disconnect ...
$ docker network rm ...

Retour sommaire

Les volumes

§id:volumes§;

Lorsqu’on détruit un conteneur, on supprime aussi les modifications apportées au système de fichier.

Les conteneurs ne partagent pas leur système de fichiers entre-eux.

Les volumes apportent une solution à cela.§fragment

Les volumes

  • permettent la persistance des données au delà du conteneur
  • permettent le partage de données entre plusieurs conteneurs

Types

  • un dossier de la machine hôte
  • un volume géré par docker

Volume hôte

On utilise l’option -v LOCAL_PATH:PATH_ON_CONTAINER:MODE

  • LOCAL_PATH : le chemin absolu sur l’hôte
  • PATH_ON_CONTAINER : où brancher ce dossier dans le conteneur ?
  • MODE (optionnel) : mode d’accès, principalement rw (par défaut) et ro
$ docker container run --rm -it -v /:/monhote:ro debian:jessie /bin/bash

Volume docker

  • Gestion des volumes avec un workflow dédié : create, ls, rm§fragment
  • Abtraction du backend de stockage : local, partage réseau, baie de stockage…§fragment

Volume docker

Lister les volumes

$ docker volume ls
DRIVER              VOLUME NAME
local               2bd7394a7adebb03f073bd82048048124578e0b506adea3064fda5d38ef7b678
local               data-telegraf
local               e0c1ad4b13ed61067082a3511feaae14dbdcacd19632594c129548e241575e0c
local               minidlna
local               mongodb
...

Quand un volume est créé sans nom, docker le nomme un peu étrangement…§fragment

Volume docker

Créer un volume

$ docker volume create --name NAME [OPTS]

On peut préciser le driver à utiliser (dépend du backend, par défaut local).

Volume docker

Créer un volume lors de la création d’un conteneur

$ docker container run -v [NAME]:[PATH_ON_CONTAINER]:[OPTS]

§fragmentUn peu comme pour un volume hôte, mais avec un nom au lieu d’un chemin.

Volume docker

Les métadonnées d’une image peuvent forcer la création d’un volume :

docker image inspect rok4/data-bdortho-d075                                            
[{...
    "Config": {...
        "Volumes": {
            "/rok4/config/pyramids/ORTHO_JPG_PM_D075": {}
        }
    },
...]

Volume docker

Supprimer un volume

$ docker volume rm NAME

Volume docker

Supprimer un volume lors de la suppression d’un conteneur

$ docker container rm -v CONTAINER_NAME

Ne concerne que les volumes créés automatiquement par les métadonnées d’une image.

Gestion des données à la création d’un volume

  • un volume hôte remplace totalement un chemin du conteneur.
  • un volume docker utilisé pour la première fois est initialisé avec le contenu du chemin de montage dans le conteneur.

Volumes avancés

L’option --mount permet des montages plus élaborés :

  • autant de possibilités qu’avec le fichier /etc/fstab
  • suppose que le support existe, pas de création à la volée comme avec un docker volume create (ex. : pas de création de l’export NFS)

Retour sommaire

Dockerfile

§id:dockerfile§;

Script de création d’image.

Documentation officielle sur le site de docker

Dockerfile

  • automatiser la création des images grâce à un jeu d’instructions §fragment
  • un environnement d’exécution propre lors des mises à jours §fragment
  • pouvoir reconstruire : mouvance IaC, paradigme cloud§fragment

Dockerfile

  1. On part d’une image existante
  2. Chaque ligne équivaut à lancer un conteneur et à le commiter
  3. L’image est créée avec le nom spécifié

La commande utile

Construire une image avec un Dockerfile

$ docker image build DOCKERFILE_PATH
  • DOCKERFILE_PATH est le chemin du dossier contenant le Dockerfile.

Instructions

§slide:data-transition=fade§;

Spécifier l’image de base

FROM debian:jessie

Instructions

§slide:data-transition=fade§;

Modifier les métadonnées

MAINTAINER Thibault Coupin <thibault.coupin@gmail.com>
LABEL mon_tag="ma valeur"

Instructions

§slide:data-transition=fade§;

Lancer une instruction

RUN command

Instructions

§slide:data-transition=fade§;

Ajouter des fichiers

ADD <src> <dest>
COPY <src> <dest>

Globalement identiques mais :§fragment

  • ADD supporte les URL§fragment
  • gestion du cache de build différente§fragment

Instructions

§slide:data-transition=fade§;

Modifier l’environnement d’exécution

ENV     #Variable d'environnement
USER    #Changement d'utilisateur
WORKDIR #Changement du dossier de travail

Instructions

§slide:data-transition=fade§;

Modifier l’exécution

CMD    #Commande par défaut
EXPOSE #Déclarer un port réseau
VOLUME #Déclarer un volume

Instructions

§slide:data-transition=fade§;

Paramétriser le Dockerfile

ARG <name>[=<default value>]

Utilisation : ${name:-default_value}

Instructions

§slide:data-transition=fade§;

Paramétriser le Dockerfile

docker image build --build-arg name=value .

Bonnes pratiques de conceptions

  • un conteneur est éphémère : utilisation de volumes§fragment
  • juste ce qu’il faut§fragment
  • un seul processus par conteneur§fragment

  • minimiser le nombre de couche du système de fichiers en minimisant les commandes RUN et en utilisant beaucoup de &&§fragment
  • optimiser l’utilisation du cache de build :§fragment
    • les commandes qui changent le moins en premiers (MAINTAINER, EXPOSE …)§fragment
    • les commandes ADD plutôt vers la fin§fragment

Multistage build

juste ce qu’il faut

Pour le run§fragment

Rien en rapport avec le dev/build§fragment

Un conteneur de build génère un package à copier sur le conteneur de run §fragment

Multistage build

Exemple :

FROM debian:jessie as monBuilder
RUN apt-get update && apt-get install build-essential BUILD_DEPENDENCIES
ADD https://github.com/...../master.zip /master
RUN make 

FROM debian:jessie
RUN apt-get update && apt-get install RUN_DEPENDENCIES
COPY --from=monBuilder /master/monBinaire /opt/bin/
CMD /opt/bin/monBinaire

Doc multistage build

Retour sommaire

C’est déjà fini

§icon:arrow-left§; Retour sommaire