Docker pour les null

Créer mon premier conteneur docker.

15 août 2017

Si vous lisez ceci, je suppose que vous avez au minimum un aperçu de ce qu'est Docker, je ne vais pas revenir là-dessus. En revanche, parlons du concept de microservice.

Une application web est généralement composée d'une multitude de logiciels assurant chacun des services, un exemple basique : Apache sert de serveur web, MariaDB de système de gestion de bases de données, Memcache de système de gestion de cache. Le concept de microservice consiste à cloisonner et à rendre indépendant la plupart de ces services, ils deviennent ainsi plus facilement maintenables.

L'idée dans l'utilisation de docker est d'identifier les services, la granularité souhaitée (vous n'êtes pas obligé de tout découper si ça n'a pas de sens dans votre cas...) et de créer une image par service. Dans l'exemple ci-dessus, j'aurai ainsi une image "serveur_web_apache", une "sgbd_mariadb" etc.... Ces images serviront à créer de nombreux conteneurs qui communiqueront entre eux via leurs API respectives. Si nous souhaitons changer apache par nginx, il nous suffit de faire en sorte que les conteneurs de serveurs web soient maintenant issus de l'image "serveur_web_nginx" et qu'ils possèdent les mêmes API (mêmes ports, montages réseaux etc...). Si nous avions laissé apache et mariadb comme un même service, nous aurions été obligés de réinstaller mariadb en même temps qu'nginx alors que ce changement ne le concerne pas. Notez que j'ai ici fait un découpage en services technologiques mais un service peut être de type métier : service qui joue les tests unitaires, qui met en production etc...

Les manipulations suivantes ont été testées avec un raspberry pi sous Docker version 17.05.0-ce, build 89658be.

Installer docker, à exécuter en root

curl -sSl get.docker.com | sh

Le registry public principal de docker (https://hub.docker.com) contient une multitude d'images prêtes à l'emploi. Attention, si comme moi vous êtes sur un raspberry pi, prenez garde à choisir des images compatibles avec le processeur ARM. En général le nom de ces images contient "arm" ou directement "rpi". Téléchargeons l'image du système raspbian, le dérivé de debian spécialement créé pour le raspberry pi.

Télécharger une image docker

docker pull resin/rpi-raspbian

Créons maintenant notre propre image "serveur_web_apache", basée sur l'image raspbian que nous venons de télécharger.

Le Dockerfile est un fichier de description qui servira à la construction d'une image docker. Un grand nombre de commandes sont disponibles (mapping de ports, montage de répertoire etc...) mais pour l'exemple nous nous contenterons du strict minimum : la création d'une image à partir d'une autre image.

Un Dockerfile basique, /home/pi/Dockerfile

FROM resin/rpi-raspbian

Construction d'une image à partir du dockerfile

docker build -t serveur_web_apache /home/pi/Dockerfile

# -t : nom de l'image

# sortie :
# Sending build context to Docker daemon  2.048kB
# Step 1/1 : FROM resin/rpi-raspbian
# ---> 1283aa5cac1a
# Successfully built 1283aa5cac1a
# Successfully tagged serveur_web_apache:latest

Le nom de l'image est facultatif mais c'est quand même plus pratique que d'utiliser son hash.

Lister les images docker

docker image ls

# sortie :
# REPOSITORY          TAG     IMAGE ID      CREATED      SIZE
# serveur_web_apache  latest  3a2f298cc540  2 weeks ago  656MB
# resin/rpi-raspbian  latest  1283aa5cac1a  2 weeks ago  126MB

Maintenant que nous avons une image, nous pouvons nous en servir de base pour créer des conteneurs.

Comme pour la construction d'image, le nom est facultatif. Dans un contexte industriel il sera même très fréquemment absent, nous préférerons créer un nouveau conteneur tout propre à chaque utilisation. Par exemple, lors de deux exécutions de sessions de tests unitaires, nous ne voulons surtout pas que le premier lancement ait une quelconque influence sur le déroulé du second.

Création d'un conteneur

docker run -td -p 4242:80 -v mon_site:/var/www/html --expose 80 --name informatix_container serveur_web_apache

# -t : tty, bidouille permettant d'exécuter le conteneur en continu sans qu'il s'arrête
#      puisqu'il écoute stdin.

# -d : deamon, pour qu'il tourne en arrière plan.

# -p : redirection de ports de l'hôte vers le conteneur. "port externe : port interne"

# --expose: expose un port en dehors du conteneur, il sera disponible pour les
#           autres conteneurs. Si vous utilisez l'option -p, l'exposition sera
#           automatique.

# -v : spécifie un montage pour que le conteneur ait accès à un dossier de l'hôte.

Une chose très importante à comprendre : chaque lancement de cette commande créé un conteneur différent. Si vous indiquez le même nom : "The container name "/informatix_container" is already in use by container...". Si vous modifiez votre conteneur en installant un programme, il sera indispensable de le commit et de le recréer si vous souhaitez modifier ses ports, ses montages etc...

Notez que la plupart des comportements de cette ligne de commandes auraient pu être définis directement dans le Dockerfile : la ligne de lancement du conteneur s'en serait trouvée allégée. Attention toutefois à ne pas figer trop de comportements en dur afin de ne pas casser "l'aspect microservices" que doivent vous apporter vos conteneurs. Dans notre exemple, l'image décrit ici un simple serveur web apache non-lié à un site en particulier : c'est lors de la création du conteneur que j'ai délibérément choisi de le lier à un port et un répertoire propre à un cas d'utilisation. J'aurais aussi pu créer une toute nouvelle image pour mon cas particulier "serveur_web_informatix", basée sur l'image plus générique "serveur_web_apache", à vous de voir ce qui vous convient.

Lister les conteneurs docker

docker ps -a

# sortie :
# CONTAINER ID  IMAGE         COMMAND                  CREATED      STATUS        PORTS                 NAMES
# 8e23e91c2b2d  1283aa5cac1a  "/usr/bin/entry.sh..."   2 weeks ago  Up 3 seconds  0.0.0.0:4242->80/tcp  informatix_container

-a : all, liste les conteneurs actifs et inactifs

Exécuter une commande dans le conteneur

docker exec informatix_container ls -la

Ouvrir bash pour saisir des commandes

docker exec -it informatix_container bash

# -i : interactif
# -t : tty

Arrêter et redémarrer le conteneur

docker stop informatix_container

docker start informatix_container

Sauvegarder les modifications du conteneur dans une image

docker commit informatix_container serveur_web_apache_2

Supprimer les conteneurs et les images

docker container rm informatix_container
# ou
docker rm informatix_container


docker image rm serveur_web_apache
# ou
docker rmi serveur_web_apache

Exporter et importer une image depuis une archive

docker save --output serveur_web_apache_save.tar serveur_web_apache

docker load --input serveur_web_apache_save.tar

Afficher les informations d'un conteneur

docker inspect informatix_container

A bientôt !

Par
Créateur et administrateur.

Dans la même catégorie

Git : annuler le dernier commit sans perdre ses modifications
SSHFS : monter un système de fichier avec SSH
Linux : débloquer une interface graphique gelée
Gnome 3 : changer les raccourcis clavier systèmes
Bash : sortir automatiquement du script si une variable n'est pas initialisée
Bash : sortir automatiquement du script si une commande échoue
GIT : merger 2 commits
Nginx : mettre un serveur par défaut
GIT : Afficher la branche courante dans le prompt
Couper une vidéo ou une musique sous linux
Debian / Ubuntu : installer HTTPS pour APT
Filtrer les lignes affichées par la commande tail
Apache 2 : Créer des sous-domaines dynamiques
Transférer des fichiers sur un smartphone android sans câble USB
Comment connaitre la taille d'un dossier sous linux ?
Surveiller la sortie d'une commande avec watch
Comment lancer ou arrêter un script au démarrage de Linux ?
Comment connaître la version de mon OS Linux ?
Comment afficher le cache ARP sous Linux ?
GIT : les commandes indispensables
Comment trouver mon adresse IP publique ?
Linux : Comment configurer une adresse IP fixe ?
Comment supprimer les fichiers plus vieux qu'une date donnée en bash ?
Apache 2 : Comment changer le DocumentRoot en fonction du port ?
GIT : Comment ajouter les nouveaux fichiers automatiquement ?
Comment exécuter un script local sur une machine distante avec SSH ?
32 bits ou 64 bits ?
Ecrire dans le sudoers grâce à visudo

Commentaire(s)