Docker est aujourd'hui l'un des leaders du marché concernant la conteneurisation. Il est un élement extrêmement important sur le fonctionnement de nos infrastructures aujourd'hui. Vous allez plus bas découvrir l'environnement docker et apprendre à l'utiliser quotidiennement.
Première étape, mettre à jour le système et récupérer les packages permettant d'utiliser apt à travers HTTPS
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
Ajouter la clé GPG officielle de Docker
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Configurer le repository en ajoutant docker :
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Installer les paquets pour Docker :
sudo apt-get update & sudo apt-get install docker-ce docker-ce-cli
Ajouter le plugin permettant de manager les repositories
sudo dnf -y install dnf-plugins-core
Ajouter le repository de docker
sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
Installer docker
sudo dnf install docker-ce docker-ce-cli docker-compose-plugin
Autoriser docker & démarrer docker sur le système
sudo systemctl enable --now docker
Installez docker
sudo zypper install docker
Activez et lancez le service
sudo systemctl enable docker && sudo systemctl start docker
Vérifiez que l'installation s'est bien effectuée :
sudo docker run hello-world
Si vous avez ce résultat c'est que l'installation s'est déroulé sans problèmes :
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:(https://hub.docker.com/)
For more examples and ideas, visit:(https://docs.docker.com/get-started/)
A partir de là, peu importe si vous êtes sur un environnement debian, fedora ou autres les commandes restent les mêmes.
Quelques petites commandes avant de démarrer l'utilisation de docker.
Lister les conteneurs actifs (& inactif avec -a)
sudo docker ps
sudo docker ps -a
Lister les images
sudo docker images
Créer un conteneur
sudo docker run [nom_image]
Supprimer un ou plusieurs conteneur (& forcer la suppression avec -f)
sudo docker rm [nom_conteneur]
sudo docker rm -f [nom_conteneur]
sudo docker rm [nom1] [nom2] [nom3]
sudo docker inspect [nom]
Permet de démarrer/arrêter/redémarrer un ou plusieurs conteneur
sudo docker start/stop/restart [nom]
sudo docker start/stop/restart [nom1] [nom2] [nom3]
Permet d'éxecuter une commande à l'intérieur d'un conteneur
sudo docker exec [nom_conteneur] [commande]
Pour connaitre la liste des images existantes, rendez-vous sur le site de Docker et cherchez les images qui vous intéresse.
Pour ma part ce sera une base Debian
sudo docker run -it debian
Il me téléchargera alors la dernière version "stable" disponible (dit "latest"), l'option -it signifie ici
Si je souhaites une version spécifique de Debian (par exemple Debian Buster) il me suffit d'ajouter un tag (liste disponible ici)
sudo docker run -it debian:buster
Vous allez ensuite être "projeté" dans le conteneur puisque votre nom d'hôte a maintenant changé
Dans mon cas je suis maintenant "root" dans la "machine" 38dc873e31f6.
Par défaut si je ne précises rien après mon docker run le nom d'hôte sera généré aléatoirement (comme le nom du conteneur d'ailleurs mais j'y renviendrais après)
root@38dc873e31f6:/#
Je peux à partir de la intéragir avec mon conteneur comme s'il s'agissait d'une machine normale.
Je vais faire les mises à jour et installer apache2 mariadb-server php, mais avant histoire d'être "sûr" je vais vérifier quelle version de Debian j'ai installé.
root@38dc873e31f6:/# cat /etc/debian_version
11.5
Je sais que je suis en version bullseye 11.5, il faudra prendre cela en compte si je veux déployer des applications (ex : si vous avez un glpi ou autre présent sur debian 10 il ne sera pas automatiquement déployable ici)
root@38dc873e31f6:/# apt update && apt upgrade
root@38dc873e31f6:/# apt install apache2 mariadb-server php -y
Je peux alors démarrer apache2 et mariadb
root@38dc873e31f6:/# service apache2 start
root@38dc873e31f6:/# service mariadb start
Pour vérifier le fonctionnement d'apache vous pouvez installer lynx le navigateur CLI
Pour vérifier le fonctionnement de mariadb il vous suffit de vous connecter via la commande mysql -u root
root@38dc873e31f6:/# mysql -u root
Welcome to the MariaDB monitor. Commands end with ; or \\g.
Your MariaDB connection id is 32
Server version: 10.5.15-MariaDB-0+deb11u1 Debian 11
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\\h' for help. Type '\\c' to clear the current input statement.
MariaDB [(none)]>
Preuve que l'application est bien déployé !
Problématique mon conteneur n'est pas accessible depuis "l'extérieur", cela signifie qu'actuellement personne d'autre que moi DANS le conteneur n'a accès à l'application...
Je vais donc recommencer cela "proprement", je vais quitter puis supprimer le conteneur & en refaire un nouveau
root@38dc873e31f6:/# exit
ilan@debian-tuto:~$ sudo docker ps -a
Une fois la liste affichée vous devez vous retrouver avec ceci, les seuls éléments changeant étant le NAMES & le CONTAINER ID
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38dc873e31f6 debian "bash" 4 seconds ago Exited (0) 2 seconds ago focused_wilson
Récupérez le nom de votre conteneur ou l'identifiant et supprimez le conteneur.
sudo docker rm 38dc873e31f6
ou
sudo docker rm focused_wilson
Je recréer le conteneur mais cette fois-ci en précisant plusieurs éléments : le port sur lequel ouvrir le conteneur & le nom du conteneur
sudo docker run -it -p 80:80 --name LAMP_tuto --hostname LAMP debian
Je me retrouve enfin dans le conteneur, il ne me reste plus qu'à faire les MàJ et installer apache2,etc..
root@LAMP:/# apt update && apt upgrade
root@LAMP:/# apt install apache2 mariadb-server php -y
Je lance ensuite apache
root@LAMP:/# service apache2 start
Depuis une machine dans le même réseau que votre machine physique vérifiez si le conteneur est joignable
Pour être sûr qu'il s'agit bien de ce conteneur, je vais modifier la page html
root@LAMP:/# echo "bienvenue sur mon site de test" > /var/www/html/index.html
Le conteneur est donc bien joignable depuis mon ip physique !
Super ! Vous avez maintenant créer votre premier conteneur et lui avez permis d'être joignable depuis l'extérieur !
La problématique que je vous ai pas expliqué plus haut (même si vous l'avez peut-être compris au moment où j'ai refais un conteneur) est qu'à chaque déploiement de conteneur, il déploie le contenu de l'image.
Si je souhaites donc redéployer un LAMP il faudra que je répète exactement la même procédure, c'est-à-dire, créer le conteneur avec l'image, faire les MàJ, installer apache2, etc...
Terminer tout ça ! Vous pouvez créer une image personnalisée qui aura déjà certains paquets installés !
Pour cela il vous suffit d'utiliser la commande "docker commit" qui possède la synthaxe suivante
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Pour créer mon image LAMP admettons, je vais simplement reprendre mon conteneur précédent (LAMP_tuto) et "déplacer" le contenu de celui-ci dans une image.
sudo docker commit LAMP_tuto lamp
Les noms d'images n'acceptent pas les majuscules !
Je retourne vérifier ma liste d'images
sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
lamp latest 7aa6b9fb05d0 25 hours ago 554MB
debian latest d8cacd17cfdc 2 days ago 124MB
On retrouve bien mon image de "base" appelée "debian" avec le tag latest et au dessus mon image "lamp" a bien été créé ! Remarquez également que l'espace de stockage n'est pas le même puisque l'image de base debian fait seulement 124MB là où celle avec apache,mariadb,php et leurs dépendances est à 554MB.
Malgré cela je penses qu'on est d'accord pour dire que ce n'est pas beaucoup !
Pour ne pas vous embêter à trouver des noms pour vos images, vous pouvez également modifier les tag
sudo docker commit LAMP_tuto debian:lamp
sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
debian lamp 6581df38f5a7 25 hours ago 554MB
lamp latest 7aa6b9fb05d0 25 hours ago 554MB
debian latest d8cacd17cfdc 2 days ago 124MB
Le resultat est "le même" sauf que vous avez taggué "lamp" à l'image debian.
Chacun sa méthode j'ai envie de dire il n'y a pas réellement de "bonne" ou de "mauvaise".
Personnellement j'utilise les tag pour l'utilisation qui est fait actuellement de manière "conventionelle" c'est-à-dire les différentes versions de mes images
Par exemple le wiki sur lequel vous êtes actuellement est l'image wiki:v5 me concernant.
Super ! Vous savez utiliser & gérer les images avec Docker !
Les volumes sur dockers sont des éléments extrêmement important, ils permettent d'enregistrer le contenu de vos conteneurs sur un emplacement qui ne bougera pas après la suppression de celui-ci.
En effet si l'on prend l'exemple du conteneur précédent, si j'apporte des mises à jour a mes pages web (ex : Ajout de CSS, ajout de menu, etc..) et que j'oublie de faire un commit, je me retrouverais a recréer un conteneur avec le contenu présent AVANT les modifications !
Pour cela, nous avons la solution des volumes.
Vous pouvez créer un volumes avant de l'ajouter sur un conteneur ou le créer en même temps que la création du conteneur
Avant la création du conteneur :
sudo docker volume create volume_tutoriel
sudo docker run -it -v volume_tutoriel:/var/www/html -p 80:80 --name LAMP_tuto --hostname LAMP lamp
Pendant la création du conteneur :
sudo docker run -it -v volume_tutoriel:/var/www/html -p 80:80 --name LAMP_tuto --hostname LAMP lamp
Ici le dossier /var/www/html du conteneur sera enregistré dans le "volume_tutoriel", les volumes sont par défaut stockés dans /var/lib/docker/volumes
Maintenant vous pouvez facilement ajouter du contenu à votre conteneur sans être présent dedans !
Si je reprends mon exemple précédent, je créer le conteneur avec le volume
ilan@debian-tuto:~$ sudo docker run -it -v volume_tutoriel:/var/www/html -p 80:80 --name LAMP_tuto --hostname LAMP lamp
root@LAMP:/# exit
Une fois le conteneur créé, je modifie le fichier html
ilan@debian-tuto:~$ sudo echo "test de modif" > /var/lib/docker/volumes/volume_tutoriel/_data/index.html
Si vous n'avez pas le droit de modifier index.html, connectez vous temporairement en root ou modifier les droits d'accès sur le fichier.
Je lance le conteneur et je lance apache
sudo docker start LAMP_tuto
sudo docker exec LAMP_tuto service apache2 start
Si je retourne sur ma page web le contenu a bien été modifié
Super ! Vous savez maintenant comment créer et intéragir des volumes.
Par défaut Docker est séparé en 3 réseau, le réseau "bridge", le réseau "host" et le réseau "null"
Ici nous allons nous concentrer sur les réseaux dit "bridge", ces réseaux sont ceux qui vont nous permettre de rendre nos conteneurs disponibles sur le réseau.
Docker possède un système de gestion de réseaux "interne", un peu comme les virtuals switch sur des hyperviseur.
Tous les conteneurs sont par défaut créés sur le réseau "bridge" sauf si on spécifie autre chose.
Pour lister les réseaux effectuez la commande suivante
sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
d2907a07e4b4 bridge bridge local
80d20f8ab3da host host local
75929add81ea none null local
On retrouve bien les réseaux cités plus haut avec une particularité en plus le "scope". Docker possède deux "scope" -> Local et Swarm, la différence entre les deux est "simple".
Je n'aborderais pas dans ce tutoriel les détails du fonctionnement du scope swarm.
Pour ajouter un nouveau réseau, il suffit de faire la commande suivante
sudo docker network create reso_test
Pour vérifier la configuration de ce réseau, vous pouvez inspecter son contenu
sudo docker network inspect reso_test
[
{
"Name": "reso_test",
"Id": "2e4116ec64e2a6b3ae99dcd05fb04dcb62a0f958e8c985945ec862c86830ac76",
"Created": "2022-10-26T16:13:15.118113083+02:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
On peut y appercevoir le subnet, la gateway, si l'ipv6 est enable ou non, etc...
Vous pouvez donc personnaliser ce réseau si vous le souhaitez, par exemple avec la commande ci-dessous je vais créer un réseau "reso_test_10" qui sera en 192.168.10.0/24, une gateway en 192.168.10.254, un scope local, un driver bridge
sudo docker network create --driver bridge --scope local --subnet 192.168.10.0/24 --gateway 192.168.10.254 reso_test_10
Pour ajouter un conteneur au réseau reso_test_10
sudo docker run -it -v volume_tutoriel:/var/www/html -p 80:80 --name LAMP_tuto --hostname LAMP --network reso_test_10 lamp
Super ! Vous savez maintenant créer vos propres réseaux avec Docker !
Les variables d'environnement sont présentes dans tous systèmes d'exploitations et nous facilitent bien la tâche parfois. De $PATH à $HOME ou autre, ces variables là sont extremement importante à partir du moment où vous souhaitez commencer à automatiser/développer des éléments pour votre système.
Pour ajouter une variable d'environnement à votre conteneur, il vous suffit d'ajouter l'option --env, l'option s'attend à recevoir alors deux éléments
Cela devient pratique lorsque vous souhaitez vous faciliter la tâche sur certaines gestions, par exemple l'image itzg/minecraft-server attend des variables d'environnement pour : la version de minecraft, la politique de confidentialité, le type de serveur, etc...
Imaginez maintenant la même chose pour vos mais avec une application comme GLPI, Zabbix, etc...
La commande ci-dessous me permet d'ajouter la valeur "test_v1" à la variable d'environnement "test"
sudo docker run -it -v volume_tutoriel:/var/www/html -p 80:80 --name LAMP_tuto --hostname LAMP --network reso_test_10 --env test=test_v1 lamp
Une fois dans le conteneur affichez la variable
root@LAMP:/# echo $test
test_v1
Comme vous le voyez la variable a bien été appelé et vous pouvez donc l'utiliser pour des scripts ou pour d'autres instructions !
Super ! Vous savez utiliser les variables d'environnement !
Dockerfile est un moyen de créer des images docker de manière plus "simple" et plus "personnalisable".
La méthode est très simple comme expliqué sur le site officiel Docker , il suffit simplement de créer un fichier avec pour nom "Dockerfile" et de le remplir avec les différents arguments de la documentation.
Dockerfile fonctionne selon un système "INSTRUCTION arguments" ce qui signifie que vous spécifiez d'abord ce que vous souhaitez faire puis préciser quels éléments vous voulez y associer.
Par exemple :
L'instruction FROM attend de recevoir en argument le nom d'une image (officielle ou personnalisée) ce qui donnerait
FROM mon_image_lamp:mon_tag_perso
Le tag n'est comme d'habitude pas obligatoire comme pour la création d'un conteneur mais est importante en fonction du contexte, pour vous prendre un exemple vous pouvez avoir une image avec la même application (ex : glpi) mais avoir une image basé sur Debian et une autre basé sur Fedora.
Ainsi vous pouvez spécifier si vous souhaitez utiliser l'image base Debian ou base Fedora (ex : glpi:deb vs glpi:fed)
Ci-dessous retrouvez un exemple de docker file avec en commentaire (#) des explications sur les instructions
sudo nano Dockerfile
# Défini l'image utiliser pour la base de l'image
FROM debian
# Qui gère et maintien l'image (qui est l'admin/dev)
MAINTAINER ilan
# Copie le dossier local vers le conteneur
COPY /dossier/local /dossier/conteneur
# Déclarer des variables d'environnement
ENV test=toto
# Exécute des commandes dans le conteneur
RUN apt update && apt install -y apache2 mariadb-server php
# Copie ou télécharge des fichiers dans l'image
ADD /dossier/local /dossier/conteneur
# Modifier le répertoire courant au démarrage du conteneur (= cd)
WORKDIR /tmp
# Exposer des ports (mais n'ouvre pas le port sur le conteneur, pour cela utilisez -p au moment du docker run)
EXPOSE 80
# A la création du conteneur avec l'image le dossier /var/www/html du conteneur sera envoyé dans un volume (nom généré aléatoirement)
VOLUME /var/www/html
# Commande exécuter lors du démarrage / paramètre par défaut lors du démarrage
CMD ["service","apache2","start"]
Déplacez vous ensuite dans le même dossier que le Dockerfile, vous pouvez maintenant build l'image
docker build -t monimage:v1 ./
Docker compose est une fonctionnalité de docker permettant comme son nom l'indique de "composer" du contenu docker.
Pour faire "plus simple", docker-compose avec son système de fichier yaml de créer de multiples conteneurs afin de créer une "application" complète, rendant ainsi les différents conteneurs comme étant de simple "services".
Pour installer docker compose il vous suffit simplement d'aller chercher le paquet
sudo apt-get install docker-compose
sudo dnf install docker-compose
Une fois docker compose installé, créez un dossier pour votre projet docker-compose
sudo mkdir tutorial_compose
Créez ensuite un fichier docker-compose.yml
sudo nano tutorial_compose\docker-compose.yml
Ci-dessous, voici un exemple de fichier docker-compose qui me permet de déployer wordpress, veillez à bien respecter l'indentation sinon la fichier pourrait ne pas être lu correctement
#définition de la version de docker compose
version: "2"
#définition des différent services
services:
#On déclare le premier service qui sera "mysql" pour la bdd de wordpress
wp-db:
#Nom du conteneur
container_name: wp-db
#Nom de l'image utilisé
image: mysql:5.7
#Déclaration des volumes a utiliser
volumes:
- database_wp:/var/lib/mysql
#Permet de préciser dans quel contexte redémarrer automatiquement (ou non) le conteneur, ici cela signifie que le conteneur redémarre to>
restart: unless-stopped
#Déclaration des variables d'environnement toujours en respectant le format variable:valeur
environment:
MYSQL_ROOT_PASSWORD: P@ssw0rd
MYSQL_DATABASE: wp-db
MYSQL_USER: toto
MYSQL_PASSWORD: toto
#On déclare le second service qui exécute un serveur web et wordpress
wordpress:
#Nom du conteneur
container_name: wordpress
# Ajout d'une dépendance, le conteneur "wordpresse" ne pourra pas démarrer avant wp-db
depends_on:
- wp-db
# Nom de l'image
image: wordpress:latest
# On déclare quel port ouvrir (toujours au format local:conteneur)
ports:
- 80:80
#Permet de préciser dans quel contexte redémarrer automatiquement (ou non) le conteneur, ici cela signifie que le conteneur redémarre to>
restart: unless-stopped
#Déclaration des volumes a utiliser
volumes:
- gestion_uploads:/usr/local/etc/php/conf.d/uploads.ini
- contenu_wordpress:/var/www/html
#Déclaration des variables d'environnement toujours en respectant le format variable:valeur
environment:
WORDPRESS_DB_HOST: wp-db:3306
WORDPRESS_DB_USER: toto
WORDPRESS_DB_PASSWORD: toto
WORDPRESS_DB_NAME: wp-db
volumes:
gestion_uploads:
contenu_wordpress:
database_wp:
Une fois que le fichier est créé vous pouvez construire les images (en étant dans le dossier créé plus tôt)
ilan@debian-tuto:~/tuto\_compose$ sudo docker-compose build
Une fois les images construites vous pouvez construire les conteneurs & les démarrer.
ilan@debian-tuto:~/tuto\_compose$ sudo docker-compose up
La commande "docker-compose up" fait également la création d'image si ce n'est pas déjà fait.
Si vous voulez les démarrer en mode détaché
ilan@debian-tuto:~/tuto\_compose$ sudo docker-compose up -d
Vos applications sont donc déployés et joignable, pour ma part si je retourne sur le navigateur j'ai bien l'installation de wordpress !
Si je vais voir dans ma liste de volumes :
sudo docker volume ls
DRIVER VOLUME NAME
local tuto_compose_contenu_wordpress
local tuto_compose_database_wp
local tuto_compose_gestion_uploads
local volume_tutorial
local volume_tutoriel
Si je vais voir la liste de mes conteneurs :
sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
49c011bb449a wordpress:latest "docker-entrypoint.s…" 2 hours ago Up 2 hours 0.0.0.0:80->80/tcp wordpress
fc579eddbd75 mysql:5.7 "docker-entrypoint.s…" 2 hours ago Up 2 hours 3306/tcp, 33060/tcp wp-db
Super ! Vous savez maintenant comment utiliser docker-compose !
Ci-dessous quelques commandes supplémentaires pour vous aider dans la gestion de docker-compose
Lister les services docker-compose actif (& inactif avec -a)
sudo docker-compose ps
sudo docker-compose ps -a
Pour démarrer/stopper/redémarer le service
sudo docker-compose start/stop/restart [nom_service]
Pour supprimer un service ou plusieurs services
sudo docker-compose rm [nom_service1] [nom_service2]
Depuis le dossier contenant votre .yml vous pouvez "mettre à jour" les images
sudo docker-compose pull
Il est possible de gérer votre environnement docker via une GUI développé par "Portainer"
Pour l'installer c'est très simple. Dans un premier temps, créez un volume
sudo docker volume create portainer_data
Une fois le volume créé, lancez le conteneur
sudo docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
A partir de là, lorsque le conteneur est up, rendez-vous sur un navigateur web et renseignez l'adresse de votre serveur suivi du port 9443
Renseignez l'identifiant souhaité ainsi que le mot de passe (1) qui doit bien dépasser les 12 caractères. Puis créez l'user (2)
Une fois cela effectué, vous serez connecté à votre système, il ne restera plus qu'à le configurer, pour cela cliquez sur "Get Started"
Votre environnement sera alors automatiquement détecté et vous permettra d'afficher votre environnement Docker. Cliquez alors dessus
Vous aurez alors accès à la gestion de vos images, conteneurs, volumes, etc... Depuis votre interface graphique.
Pour plus de détails sur la gestion via Portainer, rendez-vous sur cette page
Vous savez maintenant comment installer & utiliser docker !
Vous pouvez aller plus loin dans la configuration si vous le souhaitez, n’hésitez pas à me contacter dans ce cas ou à vous renseigner directement auprès des documentations docker disponibles sur leur site officiel.
Si vous souhaitez avoir plus d’informations ou si vous avez découvert une coquille sur ce tutoriel, merci de me contacter à l’adresse i.martel@imweb.ovh
v1 - Version initiale
v2 - Ajout de Portainer (Gestion via GUI) - 17/01/2024