Ceci est une ancienne révision du document !
Conteneurisation avec Docker
Docker est un système de virtualisation proche du sysème hote (s'il est similaire). Il permet de partager des ressources et de moins solliciter le système.
Quelques sources :
- Un serveur web docker : https://techexpert.tips/fr/apache-fr/apache-installation-docker
- Docker dans LXC : https://du.nkel.dev/blog/2021-03-25_proxmox_docker/
- chaine Xavki sur docker (+docker-compose pas loin) https://yewtu.be/playlist?list=PLn6POgpklwWq0iz59-px2z-qjDdZKEvWd
- serie d'articles : https://blog.microlinux.fr/formation-docker/
Schéma conteneur et virtualisation
Installation
Voir la méthode recommandée : https://docs.docker.com/install
Ou depuis les dépots d'Ubuntu récents :
sudo apt install docker docker-compose # si on veut utiliser des fichiers docker-compose.yaml
Mais dans doute le paquet docker-ce dispo dans les repos est-il plus pertinent ?
Mettre l'utilisateur courant dans le groupe docker :
sudo addgroup monlogin docker
Install de docker via ansible dans le role setup_machine : https://gitlab.cemea.org/cemeasi/ansible-cemea/-/blob/master/roles/setup_machine/tasks/main.yml?ref_type=heads#L73-116
Principe de fonctionnement
On peut soit récupérer une image docker existante depuis un dépot (hub.docker.com), soit la créér-adapter soi-même depuis un fichier texte nommé Dockerfile (combiné avec d'auters fichiers en option) (et l'envoyer ensuit sur le dépot).
Il faut donc distinguer :
- image docker : image “modèle”, à mettre à jour
- conteneur docker : une ou plusieurs instanciations de l'image docker de référence
Voir la version de docker : docker version
Récupérer une image : docker pull nomimage
Voir les images récupérées : docker images
Voir les images disponibles : docker search mot
Télécharger une image : docker pull nomimage:tag
Effacer une image locale : docker rmi nomimage (ou docker rmi id_image)
Chaque image peut être instanciée plusieurs fois pour avoir plusieurs conteneurs différentes, comportant chacun un nom propre.
Mettre à jour une image : docker update nomimage
Lancement d'un conteneur
Création d'un conteneur nommé : docker run -d –name nomconteneur nomimage
Exemple : docker run hello-world
Voir les instances en cours avec docker ps -a
(et leur nom en fin de colonne).
Détruire un conteneur : docker rm nomconteneur
Lancer un conteneur : docker start nomconteneur
Arrêter un conteneur : docker stop nomconteneur
Voir les conteneurs actifs : docker ps
Voir les conteneurs actifs et inactifs : docker ps -a
Chaque image docker possède plusieurs tags, par défaut “latest” est utilisé pour avoir la dernière version.
Quelques commandes utiles
docker run -it nomimage
: lance un conteneur en mode interactif, on se retrouve dans le conteneur.
docker start nomcontainer
: démarre un conteneur existant
docker exec -ti nomcontainer /bin/bash
: prend la main sur ce conteneur en lançant la commande bash
docker stop nomcontainer
: stoppe un conteneur existant
docker run –name monserveur -d -p portlocal:portdocker httpd
: mappe le port local vers le port du docker (-d : détach = laisse tourner en arrière plan).
docker logs -ft monserveur
: suivi des logs sans interuption, -t avec time, -f : comme tail -f
Besoin d'aide ?
docker info docker -h docker container -h # manage les container docker image -h # manage les images
Idem pour network, volumes, service, system….
Publier une image
docker commit <CONTAINER NAME or ID> <NEW_IMAGENAME>
et on pourra donc relancer :
docker run -it NEW_IMAGENAME
Dockerfile
Dans un dossier “mondocker” contenant un fichier index.html personnalisé, créer un fichier Dockerfile :
FROM nginx COPY index.html /usr/share/nginx/html/index.html
Dans le dossier mondocker, lancer le docker avec :
docker build -t mondocker . Puis docker run -p 8888:80 mondocker:latest
Et pointer vers http://localhost:8888 pour voir la page html customisée.
Instructions Dockerfile
- FROM : Définit l'image de base qui sera utilisée par les instructions suivantes.
- LABEL : Ajoute des métadonnées à l'image avec un système de clés-valeurs, permet par exemple d'indiquer à l'utilisateur l'auteur du Dockerfile.
- ARG : Variables temporaires qu'on peut utiliser dans un Dockerfile.
- ENV : Variables d'environnements utilisables dans votre Dockerfile et conteneur.
- RUN : Exécute des commandes Linux ou Windows lors de la création de l'image. Chaque instruction
RUN va créer une couche en cache qui sera réutilisée dans le cas de modification ultérieure du Dockerfile.
- COPY : Permet de copier des fichiers depuis notre machine locale vers le conteneur Docker.
- ADD : Même chose que COPY mais prend en charge des liens ou des archives (si le format est reconnu, alors il sera décompressé à la volée).
- ENTRYPOINT : comme son nom l'indique, c'est le point d'entrée de votre conteneur, en d'autres termes, c'est la commande qui sera toujours exécutée au démarrage du conteneur. Il prend la forme de tableau JSON (ex : CMD [“cmd1”,“cmd1”]) ou de texte.
- CMD : Spécifie les arguments qui seront envoyés au
ENTRYPOINT , (on peut aussi l'utiliser pour lancer des commandes par défaut lors du démarrage d'un conteneur). Si il est utilisé pour fournir des arguments par défaut pour l'instruction ENTRYPOINT , alors les instructions CMD et ENTRYPOINT doivent être spécifiées au format de tableau JSON.
- WORKDIR : Définit le répertoire de travail qui sera utilisé pour le lancement des commandes
CMD et/ou ENTRYPOINT et ça sera aussi le dossier courant lors du démarrage du conteneur.
- EXPOSE : Expose un port.
- VOLUMES : Crée un point de montage qui permettra de persister les données.
- USER : Désigne quel est l'utilisateur qui lancera les prochaines instructions
RUN , CMD ou ENTRYPOINT (par défaut c'est l'utilisateur root).
Un outil pour explorer les couches d'une image Docker : https://github.com/wagoodman/dive
Les volumes
Ce sont des dossiers accessibles en dehors de docker et donc mutualisables.
docker volume create VOLUMENAME
: créer un volume (pointe vers un dossier comme /var/lib/docker/volumes/VOLUMENAME/_data)
docker volume ls
: lister les volumes
docker volumes inspect VOLUMENAME
: voir les infos
docker volume rm VOLUMENAME
: efface un volume
docker volume create –name monvolume -o type=none -o device=/chemin/hote/ -o o=bind
: créer un volume qui pointe vers la destination voulue.
docker run -ti -v nomvolume:/chemindockerdossier monimage
: -v spécifie le volume à utiliser.
docker run -ti -v /chemin/complet/nomdossier:/chemindockerdossier monimage
: pour monter un dossier local dans un dossier dockerisé.
Ou sur une parition non montée :
docker volume create -o type=ext4 -o device=/dev/sdb1 –name partitionexterne
Network
Pour créer des réseaux entre plusieurs conteneurs de types possibles :
- bridge : crée un réseau interne pour vos conteneurs ;
- host : ce type de réseau permet au conteneur d'avoir la même interface que l'hôte ;
- none : comme le nom l'indique, aucun réseau pour les conteneurs ;
- overlay : réseau interne entre plusieurs hôtes.
docker network create test
: créer un réseau
docker network ls
: voir les réseaux
docker network inspect test
: voir en détails le réseau test
docker network create –subnet 10.0.50.0/24 –gateway 10.0.50.254 –ip-range 10.0.50.0/28 test2
: Créer un réseau personnalisé
Docker créer une interface pour chaque réseau créé (ip a).
docker run -ti –network test –name ctest image
: rattacher un docker à un réseau existant
docker network connect test ctest
: connecter un conteneur ctest à un réseau existant
docker network rm test
: effacer un réseau
log via journald
Actifs sur toutes nos machines. Pour que les logs docker arrivent dans journald, ce qui permet une persistence, ainsi que tous les outils pratiques de filtrage de journald, il faut configurer le logging-driver dans /etc/docker/daemon.json
:
{ "log-driver": "journald" }
Ensuite, si on veut filtrer, plusieurs options :
- sur le nom du conteneur :
journalctl CONTAINER_NAME=scribe-scribe-1
- sur l'ID court de conteneur :
journalctl CONTAINER_ID=f541054ab4e7
Plus d'infos ici : https://docs.docker.com/config/containers/logging/journald/
On peut bien sur combiner avec d'autres filtres :
journalctl CONTAINER_NAME=scribe-scribe-1 -b -1 # Pour le dernier boot uniquement journalctl CONTAINER_NAME=scribe-scribe-1 --since yesterday # Pour les logs depuis hier journalctl CONTAINER_NAME=scribe-scribe-1 CONTAINER_NAME=scribe-dmp-server-1 #Pour avoir les logs de plusieurs containers d'un coup
Cas particulier sous PVE
Penser à activer le keyctl=1 pour docker
En cas de disque saturé, docker peut renvoyer des trucs bizarres sur des fichiers qu'il croit encore existants :
systemctl stop docker && rm -Rf /var/lib/docker/image/vfs && rm -Rf /var/lib/docker/vfs && systemctl start docker
Et patienter avant de relancer un build…
Purge
Les usages mutliples de docker génèrent des fichiers liés au volume, au réseau au cache. Ce qui représente à la longue un espace conséquent dans /var/lib/docker (20 Go chez moi).
Un nettoyage complet peut s'effectuer avec :
docker system prune -a # suppresion des images, conteneur, réseau, volumes, cache...
Et hop : réduction à 40 Mo !
Docker-compose
Permet de composer plusieurs docker ensemble, une stack de conteneurs, à partir d'un fichier .yml
Il est nécessaire d'installer docker-compose (via pip par exemple).