Virtualisation Docker
🤚 Attention, ce texte date d'une autre époque de l'histoire de Docker (2014/2015) alors que le format des conteneurs n'était pas encore standardisé. Le document se trouve ici pour mémoire en vue d'un meilleur contenu.
- 1. Virtualisation par container
- 2. Concepts internes Docker
- 3. Installation
- 4. Opérations de base
- 5. Administration de containers et d'images
- 6. Construction d'une image à partir d'un Dockerfile
- 7. Divers
1. Virtualisation par container
Le projet Docker est une solution de virtualisation logicielle, légère, dite par isolateur ou par container.
En matière d'isolation logicielle, d'autres solutions sont disponibles telles que :
- LXC
- OpenVZ
- BSD Jails
- Zones Solaris
Les avantages de ce type de virtualisation tiennent aux performances d'exécution des processus logiciels : démarrage immédiat, surcharge presque nulle, déploiement manuel ou automatique immédiat. Par exemple LXC qui utilise les mêmes capacité du noyau que Docker vise plutôt à créer des machines virtuelles légères au sens fonctionnel (avec un noyau partagé). Cette vue est concurrente à la virtualisation matérielle déjà supportée par des projets comme Xen, KVM ou VirtualBox.
On pourrait illustrer cette technologie avec LXC (libvirt) ou OpenVZ (Proxmox VE) mais Docker connait actuellement un essor qui vise à construire une solution complète, sécurisée et évolutive, soit un véritable écosystème pour la mise à disposition d'applications à partir d'éléments natifs du noyau Linux. L'objectif n'étant pas de fournir des VM au sens propre. On sera donc attentif à distinguer les concepts de machines virtuelles et de container.
D'autre part, les deux types de virtualisation "hardware" et "software" peuvent aussi être complémentaires. Combinée aux technologies de virtualisation matérielle, la virtualisation logicielle Docker complète les infrastructures de l'informatique en nuage (cloud) en répondant à ses besoins notamment en élasticité, en gain de performances, en facilité de gestion, etc.
1.1. Docker présentation
- Projet open source écrit en GOlang
- Automatiser le déploiement d’applications à l’intérieur de containers logiciels.
- La technologie est portée par la virtualisation des espaces nommés du noyau Linux.
- Très forte croissance de développement communautaire depuis sa reprise en 2014.
- Docker-engine est le projet qui permet de créer des containers.
1.2. Container
"A container is a self contained execution environment that shares the kernel of the host system and which is (optionally) isolated from other containers in the system." (https://github.com/docker/libcontainer)
Un container est un environnement d'exécution complet :
- qui partage le noyau du système hôte
- et qui est éventuellement isolé des autres processus du système.
1.3. Docker objectifs
Les objectifs de docker se résument dans son slogan :
Build, Ship and Run
Any App, Anywhere
Soit :
- Construire et partager efficacement des images de logiciels et d’applications.
- La mise en production de ces logiciels est exécutée sous forme de containers (environnement virtuel, VE) totalement ou partiellement isolés selon les besoins.
- Sur n’importe quelle plateforme, n’importe où.
1.4. Modèles traditionnels, hyperviseur et container
Docker se positionne dans un de ces trois modèles de virtualisation :
- Modèle traditionnel : 1 PM = HW/OS + bin/libs/app
- Modèle hyperviseur (Hardware) : 1 VM = OS guest + bin/libs/app
- Modèle container (Software) : 1 VE = bin/libs/app
1.5. Isolation logicielle
Contrairement à la virtualisation hyperviseur type 2 qui supporte les applications des machines virtuelles avec leur OS et leurs librairies, docker fournit un niveau supplémentaire d’abstraction et d’automation dans le cadre de la virtualisation légère OS. Des containers indépendants fonctionnent comme une seule instance Linux, évitant ainsi la surcharge de démarrage et d’utilisation une machine virtuelle.
Les propriétés d’isolation du noyau sont assurées par :
- Les namespaces (espaces nommés) du noyau Linux isolent complètement une application du point de son environnement d’exécution : processus, réseau, ID des utilisateurs et montage de système de fichiers.
- Les cgroups fournissent le support à l’isolation des ressources CPU, mémoire, stockage (block I/O) et réseau. C'est aussi via les cgroups que l'on attribue les ressources RAM/CPU aux containers.
- Docker inclut la librairie libcontainer comme référence d’implémentation des containers (structure/fonctionnement). Il est construit autour de libvirt, LXC et systemd-nspawn.
1.6. Virtualisation type 1 et containerisation
On peut combiner les deux modèles en profitant des avantages de gestion, de performance et d'évolutivité liés à chacun :
- un ou des containers enveloppés dans une VM
- une VM enveloppée dans un container
Source : https://mainframedebate.com/2015/03/20/virtualization-vs-containerization/
Un ou des containers dans une machine virtuelle (VM).
On retrouve ici plusieurs couches :
- Une couche Applications (Containers, services)
- Une couche Machines (Machines virtuelles, OS, noyau)
- Une couche Matériels (Hyperviseur, Ressources de calcul, de stockage et réseau)
Deux exemples d'intégrations :
Une machine virtuelle dans un container
Ce modèle se propose d'exécuter une instance VM dans un container.
Libvirtd dans un container :
- Rancher
- https://github.com/ianblenke/docker-kvm
- https://www.projectatomic.io/blog/2014/10/libvirtd_in_containers/
- https://github.com/dhiltgen/machine/commit/e5d159c17fc9ef497a1933c83b69d2b8d1e6f168
1.7. Ecosystème Docker
- Registry : dépôt d'images.
- Compose : outil de composition.
- Swarm : cluster.
- Shipyard : web UI/API.
- Docker Machine : outil multi-os pour déployer des containers localement, chez des fournisseurs de services.
2. Concepts internes Docker
- Images : contenu statique de l’application (FS RO)
- Containers : image exécutée (FS RW)
- Links : permet la communication entre containers
- Volumes : permet de séparer l’application elle-même (éphémère, volatile) des données (persistantes, locale, distantes, partagées ou non).
- Index : contient les données utilisateurs, mots de passe, tags
- Registry : sert les images en faisant référence à un index
- Repository : endroit de stockage des images
- Dockerfile : déclaration des actions pour créer (build) une image
2.1. Virtualisation par container
Container = Exécution RW d’une image dans un espace isolé du noyau.
2.2. Build Ship Run
Image = modèle RO, contenu statique d’une application (fichiers)
2.3. Images
Une image est un modèle statique d’un système de fichiers en mode Read-Only (RO). Il peut s’agir du rootfs Debian ou de n’importe quelle distribution. On travaille en général à partir d’une image de base.
2.4. Images en couches UFS
Les modifications sur les images sont enregistrées en couches de FS qui peuvent fusionner. Le système utilisé est Union File System. Il crée une relation de parenté entre les images
2.5. Opérations de création les images
- Images (distributions) de base déjà prêtes
- Récupération d’images
- Construction d’images
- Diffusion d’images
2.6. Images et containers
Les containers sont les exécutions en mode RW de ces images en tant qu’environnements virtuels.
2.7. Containers
Un container est un espace utilisateur du noyau isolé par des namespaces :
- pid namespace: isolation du processus (PID: Process ID)
- net namespace: gestion des interfaces réseau (NET: Networking)
- ipc namespace: gestion des ressources IPC (IPC: InterProcess Communication)
- mnt namespace: gestion des points de montage (MNT: Mount)
- uts namespace: isolation du noyau et des identifiants de version (UTS: Unix Timesharing System)
- user namespace : UUID * Les paramètres cgroups permettent notamment de définir des profils de limites de partages de ressources.
2.8. Gestion des applications
Le processus de conception des images permet de créer, distribuer et gérer des applications de manière aisée, rapide, évolutive, sur n’importe quelle plateforme.
La technologie épargne le redémarrage d’un OS invité qui supporte l’application. On évite de la sorte des pertes en surcharge et on obtient des gains en performance.
Toutefois, l’absence d’OS invité implique aussi que les containers soient éphémères et jetables. Pour garder les données utilisateurs, il faut utiliser des Volumes qui permettent au container d’écrire sur un FS natif du système.
2.9. Résumé processus de déploiement
- Conception d'images (Dockerfile)
- Construction des images (Build)
- Mise à disposition sur un server d'images (Push vers Registry)
- Déploiement des images sur les machines Docker (Pull vers Docker Hosts)
- Configuration des containers (calcul, stockage et réseau)
- Exécution des images (démarrage des containers)
Ce processus peut être réalisé manuellement ou de manière entièrement automatisée.
3. Installation
3.1. Dépendances
- Une plateforme physique ARM ou Intel/AMD
- Un accès à l’Internet
- Des projets et de la créativité
Logiciels pré-requis :
- Version du noyau 3.8
- Architecture 64 bits
- Du stockage pour les images et les containers
- De la swap quand la RAM est faible
Docker est un exécutable contrôlé par un unit systemd
3.2. Installation et configuration
Pour Centos 7 : https://docs.docker.com/engine/installation/linux/centos/
~~ Fedora/Centos, Debian/Ubuntu/Linux Mint, Gentoo :
wget -qO- https://get.docker.com/ | sh
~~
Arch Linux :
pacman -S docker
~~Pour éviter d'être déçu, il est conseillé de déployer la dernière version du logiciel : wget https://get.docker.com/builds/Linux/x86_64/docker-latest -O /usr/bin/docker . ~~
Sous Centos/Fedora/RHEL, chaque démarrage de Firewalld vide la configuration iptables de Docker. Il faut donc redémarrer Docker après celui de Firewalld. Une alternative consiste à ne pas utiliser Firewalld pour gérer le pare-feu.
Le logiciel arrive avec un démon et un client. Par défaut, le service Docker (OPTIONS='-H tcp://0.0.0.0:2375'
) n’est pas exposé en public; il est conseillé d’activer SSL dans le cas contraire. Sous Centos 7, on peut configurer Docker dans les fichiers suivants :
/etc/sysconfig/docker
/etc/sysconfig/docker-network
/etc/sysconfig/docker-storage
systemctl enable docker
systemctl start docker
Pour la suite, on peut se référer au tutoriel ou à la documentation officielle de Docker.
3.3. Architecture
docker version
Client version: 1.6.0
Client API version: 1.18
Go version (client): go1.4.2
Git commit (client): 4749651
OS/Arch (client): linux/amd64
Server version: 1.6.0
Server API version: 1.18
Go version (server): go1.4.2
Git commit (server): 4749651
OS/Arch (server): linux/amd64
# uname -r
3.16.0-4-amd64
docker info
4. Opérations de base
4.1. Recherche d'images
docker search --help
DockerHub
4.2. Récupération d’images
Récupération d’images :
docker pull [OPTIONS] NAME[:TAG]
docker pull ubuntu
En pratique pour récupérer plusieurs images de base :
for dist in centos fedora ubuntu debian tianon/gentoo-stage3 base/archlinux; do docker pull $dist; done
4.3. Inventaire des images
Liste des images :
docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos latest 8efe422e6104 3 days ago 224 MB
centos 7 8efe422e6104 3 days ago 224 MB
centos centos7 8efe422e6104 3 days ago 224 MB
debian wheezy 479215127fa7 7 days ago 85.1 MB
debian 7 479215127fa7 7 days ago 85.1 MB
debian 7.7 479215127fa7 7 days ago 85.1 MB
debian latest 479215127fa7 7 days ago 85.1 MB
ubuntu 14.04.1 8eaa4ff06b53 7 days ago 192.7 MB
ubuntu latest 8eaa4ff06b53 7 days ago 192.7 MB
ubuntu trusty 8eaa4ff06b53 7 days ago 192.7 MB
ubuntu 14.04 8eaa4ff06b53 7 days ago 192.7 MB
fedora 21 834629358fe2 7 days ago 250.2 MB
fedora latest 834629358fe2 7 days ago 250.2 MB
<none> <none> acc1b23376ec 7 days ago 224 MB
base/archlinux latest dce0559daa1b 5 months ago 282.9 MB
tianon/gentoo-stage3 latest b5f45754f671 6 months ago 526.4 MB
markc/openwrt latest c234df31e584 10 months ago 8.274 MB
4.4. Lancer un container
La commande docker run
permet lancer un container à partir d'une image. Elle est suivie :
- d'une ou plusieurs options
- du nom d'une image
- d'une commande
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Si l'image invoquée n'est pas présente au moment de la création du container, elle sera téléchargée à partir de DockerHub.
Pour lancer un container en mode détaché (lancé en arrière-plan) avec un support console :
docker run -tid ubuntu bash
0508427ce94e0e08b3e09385625fa76ff0555aa84c86bf3884d1a455345c68bf
# docker ps
CONTAINER ID 0508427ce94e
IMAGE ubuntu:14.04
COMMAND "bash"
CREATED 12 seconds ago
STATUS Up 9 seconds
PORTS
NAMES clever_morse
On peut aussi lancer un container éphémère qui se contente d'exécuter une commande :
docker run centos echo "Hello World"
Dans ce cas, le container ne dure que le temps de l'exécution de la commande dans un environnement isolé. En conséquence, elle disparaît de la sortie de la commande docker ps
. Pour voir, tous les containers exécutés et en cours d'exécution, il faut utiliser la commande :
docker ps -a
4.5. Attacher un container
On peut entrer dans la console d’un container :
docker attach CONTAINER
Un container dispose d'une console accessible si un shell est exécuté dans celui-ci :
# docker attach clever_morse
root@0508427ce94e:/#
Sortir d’un container :
CTRL p CTRL q
Sortir d’un container et le terminer :
CTRL c, CTRL d, exit
4.6. Informations sur un container
docker inspect [OPTIONS] CONTAINER|IMAGE [CONTAINER|IMAGE…]
docker inspect clever_morse | grep "IPAddress"
"IPAddress": "172.17.0.2",
4.7. Manipuler les containers
Manipuler les containers :
docker start CONTAINER
docker stop CONTAINER
docker restart CONTAINER
4.8. Gestion des containers
Visualiser les logs du container :
docker logs CONTAINER
Tue un container en lui envoyant un SIGKILL :
docker kill CONTAINER
- Efface un container du disque :
docker rm CONTAINER
- Met tous les processus d'un container en pause d'exécution :
docker pause CONTAINER
docker unpause CONTAINER
- Crée un nouveau container sans l'exécuter :
docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
- Pour copier des fichiers d'un container vers l'hôte Docker :
docker cp CONTAINER:PATH HOSTPATH
Par exemple, pour copier le fichier d'un container sur l'hôte :
docker cp clever_morse:/etc/passwd .
- Il peut être utile d'exécuter une commande dans un container en cours d'exécution, pour exécuter un shell par exemple :
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Si on dispose déjà d'une console sur l'hôte Docker, il peut sembler inutile d'ajouter un service SSH dans un container.
- Supprimer tous les containers stoppés :
docker rm $(docker ps -a -q)
5. Administration de containers et d'images
5.1. Création d’une image à partir d'un container existant
Cet exemple illustre la création d'un serveur Web Apache comme container.
- Lancement d'un container de base
dev1
en y installant le logiciel :
docker run --name dev1 centos yum install httpd -y
- Conversion du container
dev1
en imagemoi/httpd
:
docker commit -a "moi" -m "http service" dev1 moi/httpd
On recommande la construction d'une image avec un minimum de couches.
5.2. Suppression d'une image
- Suppression d’une image
docker rmi ubuntu
5.3. Ports TCP/IP exposés
Pour lancer apache dans un container avec l'image créée plus haut et pour rendre le service disponible sur l'hôte Docker sur le port TCP 8080, on peut tenter la procédure suivante dans le but de comprendre le fonctionnement d'un container. Cette approche n'est jamais recommandée.
Lancer un container qui expose 8080:80
docker run -ti --name dev2 -p 8080:80 moi/httpd bash
Créer un fichier /start.sh
à la racine du container
cat << EOF > /start.sh
#!/bin/bash
rm -rf /run/httpd/* /tmp/httpd
/usr/sbin/apachectl -D FOREGROUND
EOF
chmod +x start.sh
Sortie de la console
CTRL-p CTRL-q
A titre d'illustration, on peut entrer à nouveau dans le container :
docker attach dev2
Exécuter le script de démarrage
docker exec -d dev2 /start.sh
Vérifications
docker ps
Apache rend le service sur le port TCP 80 qui est devient accessible sur TCP 8080 du docker-engine. On "expose" le port d'un container sur un port de l'hôte.
On peut examiner la page par défaut httpd sur l'hôte (docker-engine) TCP8080 :
curl http://127.0.0.1:8080/
Arrêter le container et en faire une nouvelle image
docker stop dev2
docker commit -a "moi" -m "http service" dev2 moi/httpd
Tester la nouvelle image sur un container
docker run -d --name dev3 -p 8080:80 moi/httpd /start.sh
docker ps
curl http://127.0.0.1:8080/
5.4. Réseau
# docker network ls
NETWORK ID NAME DRIVER
d71611ff46d6 none null
cb8b4e72ee3c host host
ffea9fae78ff bridge bridge
# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "ffea9fae78ff16e1b4f64edaeab8311cfc0f740c5a9117b6fb5a732a275293df",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.0/16"
}
]
},
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
}
}
]
5.5. Volumes (data volumes)
Un volume (data volume) est un répertoire spécial au sein d'un ou plusieurs containers qui outre-passe UFS (Union File System).
- Un volume est initialisé au démarrage d'un container. Si le container sert de modèle à une image, les données du volume sont copiées dans l'image.
- Un volume peut être partagé et réutilisé par plusieurs containers.
- Les changements dans un volume sont réalisés directement.
- Les données d'un volume persistent même si le container est effacé.
Monter un volume
- Monter un volume sur
/var/ww/html
# docker run -it --name dev4 -p 8080:80 -v /var/www/html moi/httpd /start.sh &
- Vérifier l'emplacement du montage
# docker inspect dev4 | grep Source
"Source": "/var/lib/docker/volumes/91c7e31a3b762d6264ce1a1f5dd1dc2a4207f1902dd9a4325e75f6ae66b73f78/_data",
- Modification du fichier
/var/ww/html/index.hml
dans le container
# echo "test http dev4" > /var/lib/docker/volumes/91c7e31a3b762d6264ce1a1f5dd1dc2a4207f1902dd9a4325e75f6ae66b73f78/_data/index.html
- Redémarrer le container et vérifier le fichier servi
# docker start dev4
# curl 127.0.0.1:8080
test http dev4
Monter un répertoire de l'hôte dans un ou plusieurs containers
- Création du répertoire source et du fichier
# mkdir -p /opt/dev5/html
# echo "test http dev5" > /opt/dev5/html/index.html
- Démarrage du container et vérification
#docker run -it --name dev5 -p 8080:80 -v /opt/dev5/html:/var/www/html moi/httpd /start.sh &
#curl 127.0.0.1:8080
test http dev5
#echo "test http dev5 v2" > /opt/dev5/html/index.html
# curl 127.0.0.1:8080
test http dev5 v2
#docker run -it --name dev5bis -p 8081:80 -v /opt/dev5/html:/var/www/html moi/httpd /start.sh
# curl 127.0.0.1:8081
test http dev5 v2
- Partage de volume à partir d'un containe avec
--volumes-from
# docker run -it --volumes-from dev5 --name dev5ter -p 8082:80 moi/httpd /start.sh &
# curl 127.0.0.1:8082
test http dev5 v2
https://docs.docker.com/userguide/dockervolumes/
drivers
- local
- nfs
- lvm
- iscsi
Exercice à réaliser : https://access.redhat.com/documentation/en/red-hat-enterprise-linux-atomic-host/version-7/getting-started-guide/#install_and_deploy_an_apache_web_server_container
Gestion CPU/RAM
Réseau nsenter
- nsenter
- https://github.com/jpetazzo/pipework
- weaver
6. Construction d'une image à partir d'un Dockerfile
Dossier avec un fichier Dockerfile
ainsi que tous les fichiers à copier dans le container (scripts, paquets, etc.).
Lancer la commande docker build
Quelques images à construire soi-même :
- https://github.com/CentOS/CentOS-Dockerfiles
- Stack Lamp : https://github.com/tutumcloud/tutum-docker-lamp
- Wordpress : https://github.com/tutumcloud/tutum-docker-wordpress
- HAProxy : https://github.com/tutumcloud/tutum-docker-clusterproxy
- shipyard : https://github.com/shipyard/shipyard
- https://github.com/jfrazelle/dockerfiles
7. Divers
push
backup
restore
Ecosystème Docker
Docker registry
- https://docs.docker.com/registry/
- https://docs.docker.com/registry/deploying/
- https://docs.docker.com/registry/configuration/
Docker Compose
Docker Swarm
Docker Machine
Builds
Docker MySQL
https://mysqlrelease.com/2015/05/mysql-in-dockerland/
KVM dans un container Docker
https://github.com/dhiltgen/machine/commit/e5d159c17fc9ef497a1933c83b69d2b8d1e6f168
cf. point "1.5. Virtualisation type 1 et containerisation"
Docker quick start
- Tutoriel en ligne de 10 minutes : https://www.docker.com/tryit/
- Get docker : https://get.docker.com/
- https://slides.com/atbaker/demystifying-docker
- https://gist.github.com/botchagalupe/53695f50eebbd3eaa9aa
- Get Started with Docker Formatted Container Images on Red Hat Systems
Quelques références LXC
- https://www.flockport.com/lxc-vs-lxd-vs-docker-making-sense-of-the-rapidly-evolving-container-ecosystem/
- https://www.flockport.com/lxc-vs-docker/
- https://www.flockport.com/lxc-advanced-guide/
- https://ramirose.wix.com/ramirosen
Deux images à prendre directement
- Bind9 avec ou sans Webmin (volume) : https://github.com/sameersbn/docker-bind
- X2go Server Bureau distant via SSH : https://github.com/paimpozhil/DockerX2go