Sauvegarde / Restauration de Conteneurs DOCKER

Si vous utilisé docker depuis un certain temps vous vous êtes déjà surement posé la question de savoir comment sauvegarder l’un de vos conteneurs docker. Afin de pouvoir le réutiliser directement, plus tard, sur votre machine courante ou alors sur une autre machine. Les conteneurs sont ces couches logicielles qui sont créés à partir d’une image de docker qui contient le système de fichiers Linux respectifs et les applications out of the box.  Nous allons voir plusieurs méthodes de sauvegarde et de restauration de conteneur docker.

1.           Sauvegarde de conteneur

Pour sauvegarder nos conteneurs, nous avons plusieurs méthodes, des méthodes de sauvegarde locale et celle qui consiste à faire des sauvegardes en ligne (sur le docker hub) en privé ou en public.

Quel que soit la méthode utilisa nous commençons par enregistre les modifications faites sur un conteneur

docker commit  -p  ID_conteneur_a_sauvegarder  Nom_Conteneur_de_sauvegarde

En gros lorsque l’on veut enregistrer les modifications faites sur un compteur on utilise la commande commit qui vas se charger de créer une image qui sera un instantané de notre conteneur.  Les modifications faites sur le 1er conteneur sont donc tout enregistrées dans notre image. L’intérêt ici est de pouvoir désormais instancier un conteneur directement à partir de l’image que l’on a enregistrée. Nous pouvons sauvegarde notre image en ligne ou en local dans un fichier compressé.

Exemple : je vais enregistrer le conteneur nommé webstack_wordpress_1

docker ps
docker commit -p 040bc5052124 webstack_wordpress_1_backup
docker images

1

Nous pouvons maintenant sauvegarder cette image que nous venons de créer en ligne ou alors directement dans un fichier compressé (.tar).

a.       Sauvegarde notre image docker en ligne.

Si vous souhaitez sauvegarder notre conteneur en ligne il vous faut utiliser les commandes qui vont suivre. Bien évidemment nous supposons ici que vous avez déjà réalisé les tâches précédentes afin de faire une image de l’instantanée de notre conteneur.

Vous devez commencer par créer un compte en ligne sur le docker hub c’est gratuit à l’heure actuelle profitez-en. Ensuite vous vous identifiez sur docker avec vos identifiants.

docker login

2

Une fois authentifié on va créer un tag pour notre image à exporter

Le nom de l’image respecte une convention de nommage. Cette convention de nommage veut que si notre image n’est pas officielle il faille  mettre votre ID (votre login docker Hub) au début de l’image suivie de slash (/) ensuite suivie du nom propre que vous donnez à l’image (suivant son contenu). Exemple ID_Docker_Hub/wordpress.

Pour taguer l’image dans le repository public. Vous devez juste renseigner le nom de l’image en respectant la convention plus haut. ( docker  tag  ID_de_image   ID_Docker_Hub/webstack_wordpress_1_backup )

Donc après s’être connecté, mon ID docker étant futuriste je tape la commande.

docker  tag  9c725b3ace47  futuriste/webstack_wordpress_1_backup
docker push futuriste/webstack_wordpress_1_backup

3

NB: j’ai ajouté l’option  –f à la commande tag pour forcer le tag, car j’avais fait une erreur à la première création.

 

b.      Sauvegarder notre conteneur docker en local

Si vous souhaitez sauvegarder votre image en local dans un fichier compressé (tar) afin de le de le déplacer sur un serveur hors ligne ou même sur votre espace de sauvegarder privée. Vous devez utiliser la commande docker Save et vous lui passé le chemin et le nom du fichier de sauvegarder ainsi que le nom de l’image à sauvegarder (l’image que l’on a enregistrée précédent).

docker save -o  webstack_wordpress_1_backup.tar   webstack_wordpress_1_backup

4

2.           Restauration de conteneur

a.       Restaurer depuis un conteneur en ligne

Pour restaurer une image que nous avons sauvegardée sur le hub en ligne il suffit d’utiliser la commande docker pull pour rapatrier l’image en local comme pour n’importe qu’elle image hébergée sur docker.

docker  pull  futuriste/webstack_wordpress_1_backup

5

 

b.      Restaurer depuis un conteneur en local ou un espace privé

Pour restaurer une image que nous avons sauvegardée en local, il suffit d’utiliser la commande docker load  et de lui indiquer en paramètre le chemin d’accès à notre fichier de sauvegarde.

docker load –i  webstack_wordpress_1_backup.tar

6

3.    Docker compose

Docker Compose est un outil qui permet de décrire la composition de notre infrastructure dans le fichier docker-compose.yml au format YAML. L’avantage d’un tel outil est que pour démarrer notre stack Web qui est constitué d’un serveur web et d’un serveur mysql.  Voici un exemple de conf.

Commencont déjà par installer le module Docker-Compose sur notre stack docker via l’outil de gestion de paquets PIP.

On commence par faire une mise à jour de la liste des paquets  et on Install CURL

sudo apt-get update  && apt-get install curl 

Ensuite on télécharge le binaire de docker-compose la dernière version actuelle 1.8.0.

curl -L https://github.com/docker/compose/releases/download/VERSION_NUM/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

 NB : remplacer VERSION_NUM par le numéro de votre version de docker-compose que vous voulez Ex : la 1.8.0 qui est la dernière version actuelle.  Exemple de commande :

curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

On donne les droits d’exécution au binaire de docker compose.

chmod +x /usr/local/bin/docker-compose

Pour connaitre la version de docker compose :   docker-compose –version

Ensuite on créer un fichier YAML qui contiendra les informations de lancement de nos conteneurs docker. Créez un dossier qui nous servira de contexte pour nos conteneurs et créez-y le fichier docker-compose.yml que vous avez créé.

Créée un dossier pour notre ensemble de conteneurs

mkdir wordpress_1
nano   wordpress_1/docker-compose.yml

Mettre le contenu suivant dans le fichier en question.

mysql:
  	image: mysql:5.7
  	volumes:
	  - "./.data/db:/var/lib/mysql"
  	restart: always
	  environment:
		MYSQL_ROOT_PASSWORD: docker2016
		MYSQL_DATABASE: wordpress1
		MYSQL_USER: wordpress1
		MYSQL_PASSWORD: wordpress1

wordpress:
	image: wordpress:latest
	links:
		- mysql
	ports:
		- "9000:80"
	restart: always
	environment:
		WORDPRESS_DB_HOST: mysql:3306
		WORDPRESS_DB_NAME: wordpress1
		WORDPRESS_DB_USER: wordpress1
		WORDPRESS_DB_PASSWORD: wordpress1

Donc en gros on décrit dans le fichier docker compose l’intégralité de la commande docker run utilisée lors du lancement du conteneur. Pas besoin d’explication si vous savez comment fonctionne la commande docker run vous pouvez essaiment de déduire ce que fais ce fichier docker-compose.   Pour avoir de information sur l’ensemble des options disponible dans un fichier docker-compose aller à l’adresse  Et vous pouvez avoir différent modèle de fichier docker compose préfet a cette adresse

ensuite avant de lancer la commande de docker compose on se positionne  dans le dossier que l’on vient de créer et qui contient notre fichier YAML.

cd wordpress_1
docker-compose up –d

Si lorsque vous lancez la commande docker-compose vous avez un message d’erreur qui vous informe que le client a une version différente de celle  du serveur essayé d’ajuster la version du client que vous téléchargez afin de trouver celle qui correspond à votre serveur.

J’avais utilisé la commande :

curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose 

Avant de relancer la commande curl pour télécharger le nouveau fichier penser à supprimer l’ancien qui avait été téléchargé :

rm   /usr/local/bin/docker-compose

Pour corriger le problème, j’ai donc essayé de télécharger des versions antérieures. la version 1.4.0 avec la commande :

curl -L https://github.com/docker/compose/releases/download/1.4.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

N’oubliez pas d’attribuer les droits d’exécution à chaque fois.

chmod +x /usr/local/bin/docker-compose

Il m’affiche le message :

6 7

J’ai donc supprimé l’ancien fichier et télécharger la version 1.3.0 de l’exécutable et cella a fonctionné correctement.  J’ai utilisé la commande :

curl -L https://github.com/docker/compose/releases/download/1.3.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

Si vous souhaité désinstaller docker-compose alors que vous avez utilisé curl utiliser la commandé.

rm /usr/local/bin/docker-compose

Quelque commande docker-compose utile :

Ces commandes doivent être lancé dans l’un des répertoires qui contient un fichier YAML c’est-à-dire elle fonctionne pour un ensemble de conteneurs docker-compose uniquement.

Créer et démarrer un conteneur : docker-compose up

Créer et démarrer un conteneur en tâche de fond :   docker-compose up –d

Afficher la sortie standard des conteneurs : docker-compose logs

Arrêter les conteneurs : docker-compose stop

Supprimer les conteneurs : docker-compose rm

 

 

4.    Webographie :

 

W3BLOG

 

Les Bonnes Pratiques

Docker est un outil formidable qui permet de faire beaucoup de choses de manière plus ordonnée et plus sécurisée. Mais c’est aussi une grosse usine à gaz et si l’on ne fait pas attention il peut très vite devenir une véritable passoire ou un danger pour notre système. Voici quelque pratique à mettre en œuvre pour limiter les risques. 

1.           Créer une partition séparée pour Docker

Vu que l’on manipule plusieurs images téléchargées depuis internet il est possible que cela occupe très rapidement un trop grand espace. Le dossier par défaut ou docker stocke l’ensemble de ces données (images et containers) est le répertoire /var/lib/docker. Le souci majeur est que se répertoire est situé sous la racine / et que si nos images et nos containers venaient à occuper trop d’espace ils pourraient saturer le disque dur système ce qui rendrais le système hôte inutilisable donc par ricochet les Containers inutilisables. Une image malveillante, mal configurée ou même toute simple trop gourmande pourrait rapidement saturer le disque dur. 

Pour se prémunir de ce problème, il faut créer une partition physique séparée pour le répertoire  /var/lib/docker  dès l’installation de votre système hôte. Si votre Système est déjà installé, créer une partition logique avec LVM (Logical Volume Manager) ou alors utiliser un second disque pour docker.

Ces 2 solutions permet de définir un quota a ne pas dépasser par docker et donc vous évite de mettre votre racine / en péril.

2.           Maintenir Votre Système hôte à jour      

Cela peut paraître évident, mais que ce soit votre système hôte, le kernel ou docker engine, assurez-vous que votre système soit bien à jour. Les mises à jour permettent généralement de corriger des bugs des versions précédentes ou d’ajouter des fonctionnalités. Bien évidement il faut au préalable se rassurer que la mise à jour sera compatible avec les configurations effectuez. Pensez aussi à n’installer que des versions stables des logiciels ou même des mises à jour système pour éviter des bugs ou des effets dominos qui pourraient mettre à mal votre système.

Assurer vous donc de mettre régulièrement à jour Docker dès qu’une version stable est sortie. Il est recommandé pour docker d’avoir un noyau Linux minimum en version 3.10

interdire les communications entre les containers.

Par défaut, la communication entre tous les containers est possible sans forcément utiliser la fonction de link qui remet de lié 2 conteneurs. Une mauvaise image pourrait donc faire un sniffing et voir tout ce qui se passe sur le sous-réseau Docker de votre système hôte. C’est particulièrement dangereux, car la plupart du temps il n’y a pas de communications sécurisé entre vos containers que vous considérez comme «isolés » sur votre sous-réseau docker0.

Donc il faudrait déjà commencer par éviter d’installer s’importe qu’elle image sur votre Stack Docker et penser à vérifier le fichier dockerfile à chaque fois avant d’installer une image.

À moins d’en avoir absolument besoin et d’être sûr de tous les containers installés sur votre stack, la bonne pratique serait donc d’interdire se comportement par défaut qui permet la communication entre les conteneurs. Seuls les containers liés par link pourront  communiquer entre eux. Cela est possible nativement il suffit de passer le paramètre –icc=false au daemon. Sous debian et Ubuntu, cette opération se fait dans le fichier  /etc/default/docker en modifiant la variable DOCKER_OPTS.

DOCKER_OPTS="-icc=false"

3.           N’utilisez pas privileged pour n’importe quelle image

Quand vous lancez un container avec le mot clé –privileged, docker vas lui accorder tous les droits y compris celui de lancer un nouveau container sur la machine hôte (Docker in Docker).

 C’est par exemple le cas de l’image dockerui qui a besoin de lister les images et les containers pour éventuellement les démarrer et les arrêter.  Cette image étant fournie par un développeur de docker, nous pouvons à priori lui faire confiance, mais ce n’est pas le cas de toutes les images disponibles sur le hub ou sur d’autres registry.

Si une image demande à être privileged, demandez-vous pourquoi elle a besoin de ce droit. Même si l’utilisation de privileged est justifiée, il n’est pas forcement obligatoire de lui accorder la totalité des droits. C’est ce que permet les options –cap-add  et –cap-drop. Selon votre demande ces commandes permettent à un container privileged de lui retirer un ou plusieurs droits, ou alors à un container normal de lui rajouter les droits nécessaires.   

Exemple : ntpd (Network Time Protocol Deamon) est un serveur de temps, il ne parait donc pas absurde de lui donner la capacité de modifier l’heure de l’hôte. 

docker run -d --cap-add SYS_TIME ntpd

4.           N’utilisez pas n’importe quel registry

La plupart des images sont téléchargeables depuis le registry Docker Hub. En général et par mesure de sécurité maximale, utiliser uniquement les images «Official » proposées et validées par la société Docker. Si vous n’en trouvez pas pour une image qui vous intéresse, assurez-vous que l’image et été suffisamment téléchargés et à priori « testés » par les autres utilisateurs. N’hésitez pas non plus à getter un coup d’œil dans le Dockerfile sous GitHub afin de vous assurer que l’image correspond bien à ce qu’elle est censée faire. Pensez aussi à vérifier les images intermédiaires utilisées pour cette image. Remontez les images intermédiaires jusqu’à atteindre une image officielle ou une image from scratch. 

Si vous ne trouver pas votre compte sur le docker hub et que vous utilisiez un autre registry vérifier tous d’abord la réputation du registry que vous allez utiliser.  Mais également que la communication établie avec ce nouveau registry  se fera de manière sécurisée.  De toutes les façons par défaut docker bloque les commandes pull si elles ne sont pas sécurisées.

5.           Créer un utilisateur dans votre Dockerfile

La plupart de vos applications ne nécessitent pas d’être lancé en root, c’est même très rarement le cas. Par conséquent, il n’est pas nécessaire d’utiliser le user root dans vos containers a tous les coups. La  création d’un utilisateur dans votre image peut se faire directement depuis le dockerfile avec les 2 instructions suivantes :

RUN useradd -d /home/myappuser -m -s /bin/bash myappuser

USER myappuser

Pour vérifier l’utilisateur utilisé par vos containers lancés, vous pouvez utiliser la commande :

docker ps -q | xargs docker inspect --format '{{ .Id }}: User={{.Config.User}}'

Si user est vide, c’est que vos containers sont lancés en root.

Pour une image téléchargée, pensez à vérifier la présence de l’instruction USER dans le Dockerfile et éventuellement à surcharger l’image si ce n’est pas le cas. 

Exemple :

FROM apacheOnlyRoot

USER www-data

 

6.           Ne mapper que les ports utiles

Docker permet un mapping entre les ports déclarés par le Dockerfile et ceux ouverts sur votre système hôte via l’option –P (en Majuscule). Cela va lancer le conteneur en exposant tous les ports déclarés dans le dockerfile.

N’utilise cette option que lors des tests. Préférer toujours l’option –p (minuscule) pour vous permet de spécifier quel port de l’hôte vous souhaitez mâché avec un port spécifique du conteneur. 

docker run -p 80:80 apache

De plus, si vous n’avez pas besoin de rendre publique l’adresse IP, vous pouvez spécifier sur quelle interface réseau vous souhaitez écouter.

docker run -p 192.168.0.1:9200:9200 elasticsearch

Cette commande permet de n’ouvrir le port 9200 que pour votre réseau local. Une connexion depuis une machine hors réseau local (internet) sera refusée.

Mieux encore si vous n’avez pas besoin que le port soit exposé  à l’extérieur, mais uniquement accessible à partir de la machine hôte ou bien d’autres conteneurs.

Exemple un conteneur MySQL sur le qu’elle se connecte notre conteneur web et  administré via un conteneur PhpMyAdmin n’a pas absolument besoin d’être visible de l’extérieur un link entre le conteneur MySQL et les 2 conteneurs Web et PhpMyAdmin est suffisant donc vous n’utilisez aucune des options qui permet de maché les ports (pas de P majuscule ou minuscule) cela fera en sort que votre conteneur soit accessible uniquement depuis la machine hôte via son IP privé.

7.           Permission sur les fichiers

Vérifier que les permissions sont attribuées correctement aux fichiers manipulés par les conteneurs. Tous comme on fait des vérifications du répertoire utiliser par nos serveurs web. Pensez donc à n’attribuer que les droits nécessaires et de restreindre que maximum les fichiers accessibles sur l’hôte par les conteneurs. 

8.           Veille technologique

Pensez également à vous tenir informé des différentes avancées technologiques dans le domaine afin de toujours garder votre serveur sécurisé et d’utiliser les bonnes pratiques.

Docker est un outil formidable qui promet encore de nombreuses améliorations en termes de fonctionnalité et de sécurité. Mais la configuration par défaut de docker n’est malheureusement pas suffisante en termes de sécurité, mais représente tristement plus de 90% des installations de docker. À mon sens, beaucoup d’options devraient être activées par défaut pour réduire au maximum les risques.

   Webographie :

INOVIA

Les Bases Sur DOCKER

Dans ce tutoriel nous allons voir comment fonctionne docker et nous allons présenter quelques fonctionnalités incontournables de docker.  Si vous lisez cet article, nous supposons que vous avez déjà lu notre article précédent sur la découverte de docker ou alors vous avez lu d’autres articles sur internet, donc vous savez au moins ce qu’est docker. Mais ne vous inquiétez pas, la présentation est très explicite donc pas besoin d’être un pro sur docker pour lire cet article il faut juste savoir de quoi il est question. Bon assez bavardé…. Action.

1. Dockerfile et Cycle de vie d’un conteneur

1.1. Cycle de vie des images et des conteneurs

Avant toute chose il est important de savoir que sur docker nous manipulons des Dockerfile qui sont compilés en images et ensuite instanciés en Conteneur. Donc en gros l’on part d’un fichier Dockerfile qui nous permet de construire une image qui une fois instanciée va devenir un conteneur. Le conteneur ainsi instancié reste toutefois lié à son image de départ.

1

Voici un schéma illustrant le cycle de vie d’un conteneur avec les commandes du client Docker :

2

Quelque commandes qui vous seront surement très utiles :

docker images : Lister les images présentes en local
docker ps : Liste les conteneurs démarrés
docker ps –a : Liste tous les conteurs (ceux qui sont démarrés, arrêtés normalement ou après une erreur)
docker log : attache la sortis console à celle du conteneur.
docker stop $(docker ps -q) : arrêter tous les conteneurs lancés d’un coup de baguette magique.
docker start $(docker ps -q) : relancer en même temps tous les conteneurs qui ont été arrêtés et qui sont en mémoire.
docker exec -it Nom_Du_Conteneur /bin/bash : Se connecter au Shell d’un conteneur.
docker rm  $(docker ps -a  -q --filter "status=exited") : Effacer tous les conteneurs arrêtés d’un coup de baguette magique.

1.2 Dockerfile

Le fichier qui nous permet de créer des images s’appelle un  Dockerfile. C’est un fichier qui permet de décrire comment une image sera construite avec la commande docker build. Il contient le nom de l’ensemble des paquets qui seront installés dans l’image, les répertoires qui seront partagés par l’image, les ports qui seront exposés, l’ensemble des variables d’environnements qui seront instanciés de base, etc.

Syntaxe

Voici la syntaxe de base d’un Dockerfile qui vous permettra de décrire une image et la manière dont elle sera créée:

MAINTAINER <name>
FROM <image>
ENV <key> <value>
ADD <src> <dest>
VOLUME ["/<dir>"]
USER <user>
EXPOSE <port>
RUN <command>   ou  RUN ["exécutable", "param1", "param2"]
CMD <command>   ou  CMD ["exécutable", "param1", "param2"]

 Légende :

MAINTAINER  <name> : Auteur de l’image vous pouvez mettre votre nom par exemple

FROM <image> : Nom de l’image de base. Cela permet de ne pas partir de rien et d’utiliser une image existante. Par exemple se base sur une image Debian pour créer un conteneur APACHE.

ENV <key> <value> : Permets de définir des variables d’environnement qui seront créées lors de l’instanciation du conteneur. Ex : MYSQL_PASSWORD qui permettra à celui qui lance l’instance du conteneur de passer le mot de passe de SQL via l’option -e.

ADD <src> <dest> : Il permet de récupérer des fichiers en local et de les uploader dans l’image lors de sa compilation. Ces fichiers feront désormais partie de l’image.

VOLUME [« /<dir> »] : Répertoire monté au démarrage du conteneur et qui est externe à celui-ci. Cela permet de rendre des fichiers du conteneur directement accessible sur l’hôte.

USER <user> : Permets d’indiquer l’utilisateur Linux qui sera utilisé lors du démarrage du conteneur.

EXPOSE <port> : Permet d’indiquer les ports réseaux exposés par le conteneur. Il définir sur quels ports réseau les conteneurs communiquent avec l’extérieur.

RUN <command>   ou  RUN [« exécutable », « param1 », « param2 »] : Il permet d’exécuter une commande sur l’image lors de sa création. Ex : run apt-get install apache

CMD <command>   ou   CMD [« exécutable », « param1 », « param2 »] :

  • il faut noter qu’il ne doit y avoir qu’un seul CMD dans un Dockerfile. c’est une commande qui est lancée dans les conteneurs qui utilisent cette image à chacun de leurs démarrages.
  • Si l’image contient le serveur NGINX, il peut s’agir de lancer l’exécution du serveur NGINX au démarrage du conteneur.
  • La commande n’est lancée qu’à l’exécution du conteneur et non durant la construction de l’image
  • Cette commande peut être redéfinie dans la commande de lancement du conteneur (Docker run)

2. Réseau et partage de fichier sous docker

Sachez-le.  Quoi que vous fassiez sur docker, quel que soit l’architecture que vous déciderez de mettre en place vous utiliserez forcement de manière consciente ou non le réseau et/ou le  partage de fichier.

1.1 Partage de fichier

Le partage de fichier se fait dans un conteneur en réalisant le montage de volumes disques ce qui permettra à un conteneur d’utiliser le contenu d’un répertoire de la machine hôte. Le conteneur peut ainsi avoir des fichiers que nous aurons définis (fichier de conf par exemple) lors de son premier démarrage et ces fichiers sont stockés sur la machine hôte donc ils ne seront pas effacés lors de l’arrêt et de la suppression du conteneur.

  • Le partage de fichiers nécessite de :
    • Créer le répertoire de partage sur la machine hôte (machine utilisée pour le lancement du conteneur)
    • Spécifier le répertoire de partage au sein du conteneur (dans le Dockerfile)
  • Ajouter la ligne suivante dans le fichier Dockerfile pour indiquer quel répertoire du conteneur sera partagé :

VOLUME [« [répertoire du conteneur] »]

  • Au lancement du conteneur, indiquer le mapping entre le répertoire de partage du conteneur et la machine hôte.
  • Dans la commande docker run, ajouter l’option -v [répertoire de la machine hôte]:[répertoire du conteneur] pour mapper le répertoire de la machine hôte avec celui du conteneur:

 docker run -v [host directory]:[container directory]

ajouter :ro à la fin pour activer la lecture seule :

docker run -v [host directory]:[container directory]:ro

1.2 Communications réseau.

L’interfaçage réseau permet à un conteneur de communiquer avec l’extérieur et/ou avec les autres conteneurs. Pour définir l’interfaçage réseau, il est nécessaire de :

  • Exposer le port réseau du conteneur :
    • soit dans le fichier Dockerfile de l’image : EXPOSE [port conteneur]
    • soit via l’option –expose de la commande docker run : –expose [port conteneur]

Pour que le port réseau du conteneur soit accessible à l’extérieur de la machine hôte nous devons mapper le port réseau du conteneur avec celui de la machine hôte via l’option -p de la commande docker run. Le mappage peut être manuel ou automatique :

  • Pour Mapper manuellement les ports. Dans ce cas nous fixons manuellement qu’elles port de l’hôte et du conteneur seront mappez ensemble.
    Utilisation : 
    docker run -p ip :port/protocole   
    docker run -p [port hôte]:[port conteneur]
    docker run -p [IP]:[port hôte]:[port conteneur]
    docker run -p [IP]:[port hôte]:[port conteneur]/[protocol]
    
    NB :   
    [IP] : Adresse IP (non obligatoire),
    [port hôte] : Port de la machine hôte,  
    [port conteneur] : Port du conteneur,  
    [protocol] : Protocol réseau (non obligatoire) (exemple : tcp ou udp).

    Il est possible de définir plusieurs mapping de ports à l’aide de plusieurs options -p dans la même commande docker run: docker run …  -p 80:80  -p 8080:8080

  • Mapper automatiquement tous les ports exposés d’un conteneur avec des ports livre de la machine hôte.

L’option -P de docker run utilisée toute seule sans spécification de numéro de port permet de mapper chacun des ports exposés d’un conteneur sur un des ports de la machine hôte sur une plage comprise entre 49000 et 49900.

docker run ... -p

Il faudrait alors lancer la commande docker ps pour voir sur quels ports de la machine hôte sont mappés les ports du conteneur.

Pour qu’un conteneur puisse communiquer directement avec un autre conteneur sans forcément avoir besoin de leur affecter des ports sur la machine hôte, il est nécessaire de lié les 2 conteneurs. Pour cela on lance un 1er conteneur et ensuite au lancement du 2ème  conteneur on le lie au 1er.  Cela permet ainsi au 2ème conteneur d’avoir des informations sur le 1er Conteneur. On devra donc lancer le 2ème conteneur avec en plus le paramètre.

 Docker run …  --link=[nom conteneur lié]:[alias du conteneur] 

[nom conteneur lié] : Nom du conteneur lié qui doit être en cours d’exécution (le nom de conteneur doit avoir été défini lors du lancement de ce conteneur via l’option –name de la commande docker run)

[alias lien] : alias du lien dans le conteneur

Docker vas fournir au deuxième conteneur les variables d’environnement qui ont été déclarées pour le 1er  conteneur dans le fichier Dockerfile ou via la commande docker run (via l’aide des options -e). Ces variables d’environnements sont préfixés par le nom de l’alias qui a été formaté en majuscules. Ex: Pour un alias apache, les variables d’environnement commencent par APACHE_.

Le conteneur lié doit être en cours d’exécution et doit donc être dans la liste des conteneurs en cours d’exécution via la commande docker ps. Le nom d’alias sert au nommage des variables d’environnement dans le conteneur qui va appeler le 1er. Donc en gros pour le 2ème conteneur c’est-à-dire celui qui appel. Le conteneur 1 nommé [nom conteneur lié] sur la machine hôte aura pour nom [alias lien]  dans le conteneur.

Voilà en gros à quoi cela peut ressembler schématiquement.

3

Le conteneur 1 expose le port 111. Nous démarrons le premier conteneur :

docker run -d --name conteneur1 --expose 111 demo/image1

Nous démarrons un second conteneur en le liant avec le premier conteneur :

docker run -d --name conteneur2 -P --link conteneur1:in_conteneur1 demo/image2

Docker ajoute dans le conteneur 2 des variables d’environnement concernant le conteneur 1 pour chaque port exposé par le conteneur 1 :

Pour le port 111 du conteneur 1 :

IN_CONTENEUR1_PORT_111_TCP_ADDR=172.17.0.2
IN_CONTENEUR1_PORT_111_TCP_PORT=111
IN_CONTENEUR1_PORT_111_TCP_PROTO=tcp

Nous pouvons ainsi récupérer l’adresse IP du conteneur lié pour que le conteneur 2 puisse communiquer avec le conteneur 1.

Si le conteneur 1 exposait le port 22 avec un serveur SSH, le conteneur 2 pourra se connecter en SSH sur ce premier conteneur via le port 22 et en utilisant la variable d’environnement contenant l’adresse IP « IN_CONTENEUR1_PORT_22_TCP_ADDR« .

Exemple : MySql + Drupal

Démarrer conteneur SQL

docker run -d -v /home/joel/data/webstack/bdd/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=docker2016 --name webstack_mysql mysql

Démarrer Conteneur Drupal lié à SQL

docker run --name drupal_01 --link webstack_mysql:mysql -p 3001:80  -d drupal

Démarrage de WordPress lié à SQL

docker run --name wordpress_01 --link webstack_mysql:mysql -v /data/webstack/wordpress/1/:/var/www/html/ -p 3002:80 -d wordpress

Attention: il n’est possible de communiquer qu’avec les ports exposés d’un conteneur. Même entre 2 conteneur lié.

1.3 Changer les paramètres spécifiés lors de l’exécution du conteneur

Il n’y a pas de commande docker pour modifier les informations spécifiées via la commande docker run  du conteneur lors de l’exécution de celui-ci, que ce soit le mapping des ports réseau ou des fichiers.

Il faut alors enregistrer l’état ‘Commiter’ et redémarrer le conteneur en spécifiant le nouveau mapping de ports ou de fichiers. Lors du commit, il faut indiquer le nouveau nom d’image d’export  qui sera utilisé pour redémarrer le conteneur à partir de cette image (en gros c’est le nom de l’image de sauvegarde). Il ne faut pas utiliser le nom de l’image initial qui avait servi lors du premier démarrage du conteneur.

docker commit [identifiant] [nom image temporaire]

docker run (…) [nom image temporaire] (…)

3.    Webographie

Blog2dev  « Réseau et Fichiers » 

DÉCOUVERTE DE DOCKER

1. Présentation de docker

Docker est un logiciel open source (sous licence Apache 2.0) et un service en ligne optionnel (Docker.io) permettant de gérer des conteneurs (« dockers »). C’est un produit développé par la société de même nom. Initialement développé par un ingénieur français (Solomon HYKES), le produit a été dévoilé en mars 2013.

Docker est une application disponible aussi bien sous Windows que sous Linux. Il va vous permettre d’empaqueter d’autres applications et leurs dépendances dans un conteneur que l’on pourra ensuite déplacer et faire fonctionner sur n’importe qu’elle serveur fonctionnant sous Linux ou sous Windows (les conteneurs Linux vers des Linux et des Windows vers des Windows). Contrairement aux solutions de machines virtuelles (VM) classiques qui comprennent un système hôte (« guest OS ») et les librairies/applications utilisées par le ‘‘guest OS’’ ou l’application finale, les conteneurs ne contiennent, au maximum, que les applications/librairies finales. Cela permet donc d’avoir des conteneurs qui sont moins gourmands en ressource (HDD – CPU – RAM) que des machines virtuelles.

2

De plus une copie d’un conteneur qui ne change que la partie application ne contiendra que les différences par rapport au conteneur initial. Plusieurs conteneurs peuvent être des copies du même conteneur parent, ce qui vous permet de faire un gros gain en espace.

3

Le système qui héberge les conteneurs (l’hôte) est ainsi géré directement par le Docker Engine (en vert dans le premier schéma plus haut). Nous avons ainsi une mutualisation qui permet de lancer les conteneurs de manière presque instantanée, aussi rapide que le lancement d’une simple application. Vu que les conteneurs n’ont pas de système d’exploitation propre et utilisent celui de l’hôte, il n’y a plus de phase de démarrage et d’initialisation du système d’exploitation.

Il faut garder à l’esprit que même si l’on n’est pas dans une machine virtuelle, on dispose tout de même d’un environnement isolé (processus, système de fichier, ports réseau). L’utilisateur n’a qu’à se préoccuper que de ce qu’il veut virtualiser (les applications/services) et ne s’occupe pas du reste. Mais il est aussi possible de configurer manuellement la charge (IPs, ports, ram, processeur …) des conteneurs. La taille des conteneurs est considérablement réduite et ils sont aussi portables d’une machine docker a une autre sans configuration particulière.

2. Installation de docker

Pour faire fonctionner correctement la version actuelle de docker sous Linux, il est conseillé d’avoir un système 64bits et un kernel en version 3.10 minimum. Notre Debian 8 en version 64 bits possède toutes ces caractéristiques.

ouvrir la liste des dépôts

nano  /etc/apt/sources.list

Pensez à ajouter si vous ne les avez pas déjà, les dépôts suivants dans le fichier sources.

deb http://ftp.debian.org/debian jessie-backports main
deb-src http://ftp.debian.org/debian jessie-backports main
deb http://ftp.debian.org/debian jessie main contrib
deb-src http://ftp.debian.org/debian jessie main contrib 

Ensuite taper les commandes suivantes pour mettre à jour la liste de paquet et installer le paquet docker.

sudo apt update 
sudo apt install docker.io

NB: Toutes les manipulations faites avec les commandes docker doivent être faites avec le compte administrateur ayant le maximum de droit root. Ou alors vous pouvez ajouter votre compte utilisateur normal au groupe docker pour ne pas avoir à utiliser le compte root ou la commande sudo a tous les coups.

Maintenant pour vérifier que tout fonctionne correctement taper cette commande qui devrait lancer le conteneur hello-world qui affiche un message dans l’invite de commande avant de s’arrêter.

Vous devriez avoir ceux-ci comme résultat

sudo docker run hello-world
root@sw:/home/arsene# sudo docker run hello-world

Hello from Docker!

This message shows that your installation appears to be working correctly.



To generate this message, Docker took the following steps:

The Docker client contacted the Docker daemon.
The Docker daemon pulled the "hello-world" image from the Docker Hub.
The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.

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 Hub account:

 https://hub.docker.com



For more examples and ideas, visit:

 https://docs.docker.com/engine/userguide/


root@sw:/home/arsene#

Maintenant nous pouvons procéder à la configuration de nos conteneurs. Si vous n’avez aucun résultat rassurez-vous que le service docker est bien lancé avec la commande :

service docker status

Elle vous affichera l’état du service docker. S’il n’est pas lancé, démarrez-le avec la commande :

service docker start

3. Configurer des conteneurs sur docker

Mise en service d’un conteneur : NGINX

On commence par télécharger le conteneur :

sudo docker pull nginx

Ensuite on lance le conteneur, j’ai créé un dossier Webstack : /data/webstack/www qui va contenir les fichiers de configuration de mon serveur et les fichiers de configurations des sites web.

sudo docker run --name webstack_nginx -d -p 80:80 -p 443:443 -v /data/webstack/www:/usr/share/nginx/html/  nginx

Explication :

–name permet de donner un nom à notre conteneur

-d permet de lancer notre conteneur en tâche de fond.

-p permet de spécifier les ports ouverts Port-Hôte : Port-Conteneur  c’est-à-dire les ports de l’hôte qui seront matché avec certains ports du conteneur.

-v permet de monter un dossier ou un fichier de l’hôte vers le conteneur. Ce fichier ou dossier sera vu par le conteneur comme le fichier / dossier de départ.

/data/webstack/www : répertoire de l’hôte ou seront hébergé les sites web que nous allons créer

     /usr/share/nginx/html/ : répertoire par défaut NGINX où sont hébergé les sites.

NGINX est tout simplement le nom de l’image docker que l’on veut démarrer.

Avec la commande précédente le répertoire  /data/webstack/www  est monté en tant que répertoire  /usr/share/nginx/html/ dans notre conteneur. Le conteneur a donc un accès en lecture et en écriture à ce répertoire et nous aussi depuis la machine hôte nous pouvons modifier le contenu de ce répertoire.

Si vous ne souhaitez pas que le conteneur est un accès en écriture, mais uniquement en lecture au dossier ou au fichier que vous allez lui passer en paramètre (généralement utilisé pour des fichiers de conf. Ou même pour des sites web en fonction de vos besoins), il vous faut juste ajouter le paramètre :ro à la fin du chemin.

sudo docker run --name webstack_nginx -d -p 80:80 -p 443:443 -v  /data/webstack/www:/usr/share/nginx/html/:ro  nginx

:ro :  Read Only : il permet de monter le répertoire en mode lecture seul pour le conte

NB : Si nous n’avions pas encore téléchargé l’image nginx avec la commande docker pull, docker aurait téléchargé cette image pour nous directement avant de la monter.

Ici on peut utiliser le répertoire /usr/share/nginx/html parce qu’il a été déclaré en tant que volume dans le Dockerfile de l’image Nginx.

Liaison entre 2 conteneurs 

PhpMyAdmin et MySql

On lance tous d’abord le 1er conteneur celui auquel le second va se lier conteneur MySQL :

sudo docker run --name webstack_mysql -d -v /data/webstack/bdd/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=docker2016 mysql

Explication :

-e MYSQL_ROOT_PASSWORD=docker2016   on fixe la variable MYSQL_ROOT_PASSWORD qui contient le mot de passe qu’on décide d’attribuer au compte root de MySql au démarrage.

Ici, vous pouvez remarquer que nous n’avons spécifié aucun port pour la communication extérieure cela veut dire que seuls la machine hôte et les conteneurs qui sont liés au conteneur MySQL pourront communiquer avec lui (ceux-ci est partiellement vrais, car nous verrons que tous les conteneurs peuvent communiquer entre eux par défaut via leur IP. Mais cette fonctionnalité peux être désactivé en passant le paramètre –icc a false cette manipulation est expliquée dans le chapitre sur les bonnes pratiques de docker). Ce qui peut s’avérer être un gros avantage au niveau sécurité.

Ensuite on lance le conteneur PhpMyAdmin et on le relit au conteneur MySql.

sudo docker run --name webstack_phpmyadmin -d --link webstack_mysql:db  -p 2000:80 phpmyadmin/phpmyadmin

Explication :

–link webstack_mysql:db : il créer un lien entre le conteneur webstack_mysql (celui que nous avons créé précédemment avec MySQL) et PhpMyAdmin. PhpMyAdmin verra le nom d’hôte db dans son fichier hôte pointé sur le conteneur  webstack_mysql. Dans ce cas-ci, veillez à bien spécifier db sinon cela pourrait ne pas fonctionner. Bien évidemment, si vous avez spécifié un autre nom à MySql au lieu de (webstack_mysql) vous devez spécifier le bon nom.

Connecté vous ensuite sur : votre_ip :2000     En utilisant le compte root et le mot de passe que vous avez précédemment mis dans mysql.

5

Mysql et WordPress

docker run --name webstack_wordpress --link webstack_mysql:mysql -v /data/webstack/wordpress/:/var/www/html/ -p 3001:80 -d wordpress

Dans ce cas il utilisera les options par défaut. Pour configurer vous-même les variables utilisées, vous devez faire :

docker run --name webstack_wordpress_2  --link webstack_mysql:mysql  -p 3006:80 -e WORDPRESS_DB_USER=wordpress1 -e WORDPRESS_DB_PASSWORD=wordpress1 -e WORDPRESS_DB_NAME=wordpress1 -d  wordpress

Vous devez bien évidemment avoir créé sur votre serveur MySql l’utilisateur wordpress1 et la base de données wordpress1.

4. Arrêter / Supprimer des conteneurs et des images docker

Lorsque vous utilisé docker, différent cas de figure peuvent se poser.

  • Lister les conteneurs en court d’exécution
sudo docker ps
root@sw:/home/arsene# docker ps

CONTAINER ID        IMAGE                          COMMAND                CREATED             STATUS              PORTS               NAMES

8dbb57d6f332        wordpress:latest               "/entrypoint.sh apac   4 days ago          Up 4 days           80/tcp              webstack_wordpress_atomit
6c0f15270888        wordpress:latest               "/entrypoint.sh apac   5 days ago          Up 5 days           80/tcp              webstack_wordpress_1
39ee17373646        phpmyadmin/phpmyadmin:latest   "/run.sh phpmyadmin"   9 days ago          Up 9 days           80/tcp              webstack_phpmyadmin
0aac8e893ab1        mysql:latest                   "docker-entrypoint.s   9 days ago          Up 9 days           3306/tcp            webstack_mysql

root@sw:/home/arsene#
  • Vous souhaitez stopper un conteneur docker temporairement.

Docker stop ID_conteneur ou Nom_Conteneur :

sudo docker stop webstack_wordpress_1
root@sw:/home/arsene# docker stop webstack_wordpress_1
webstack_wordpress_1

Cette commande arête juste le serveur donc si vous faite un sudo docker ps pour lister les images en cours vous ne la verrez plus. Mais l’instance existe toujours la preuve c’est que si vous tentez de lancer un conteneur avec le même nom docker va refuser.

Pour voire la liste de tous les conteneurs docker (même ceux qui sont arrêtés), vous faite

sudo docker ps -a

Cette commande est aussi particulièrement utilise lorsqu’un conteneur refuse de se lancer (il faut noter que docker auras créé tout de même une instance).

root@sw:/home/arsene# docker ps -a

CONTAINER ID        IMAGE                          COMMAND                CREATED             STATUS                      PORTS               NAMES

94f49f7fcf81        hello-world:latest             "/hello"               11 minutes ago      Exited (0) 11 minutes ago                       desperate_jones         
8dbb57d6f332        wordpress:latest               "/entrypoint.sh apac   4 days ago          Up 4 days                   80/tcp              webstack_wordpress_atomit
6c0f15270888        wordpress:latest               "/entrypoint.sh apac   5 days ago          Exited (0) 2 minutes ago                        webstack_wordpress_1    
  • Pour supprimer un conteneur docker qui a été lancé, il faut :

Arrêter le conteneur et ensuite taper la commande :  sudo docker rm ID_conteneur ou nom

root@sw:/home/arsene# sudo docker rm webstack_wordpress_1
webstack_wordpress_1

Pour supprimer l’ensemble des conteneurs docker qui sont à l’arrêt :

docker rm  $(docker ps -a  -q --filter "status=exited")

Stopper tous les conteneurs qui tourne d’un coup :

sudo docker stop $(docker ps -q)

Lancer ensemble tous les conteneurs docker qui ont été stoppés :

 sudo docker start $(docker ps -q)

Pour se connecter à l’interface de commande d’un conteneur par exemple pour faire des mises à jour ou installer un paquet :

 sudo docker exec -it webstack_nginx /bin/bash 

10

Pour vous déconnecter un simple exit suffit

11

NB : Lorsque vous stoppez un conteneur, les mises à jour que vous aviez installées dessus vont rester. Lorsque vous allez le relancer, vous retrouverez les mises à jour. Par contre si vous supprimez un conteneur sans avoir créé une image avec ce dernier afin de sauvegarder vos modifications vous perdez automatiquement toutes les modifications que vous aviez apportées au conteneur.

5. Liste des commandes DOCKER CLI

Je vais rapidement lister les commandes Docker disponibles, en expliquant leurs rôles (informations issues des manpages Docker). Vous pouvez obtenir ces informations depuis l’invite de commande en tapant : docker -h (résultat en anglais). Vous pouvez aussi obtenir les informations sur une commande particulière en tapant : docker [commande] –help

docker attach : Joindre à un conteneur en cours d’exécution
docker build : Construire une nouvelle image à partir du code source dans le PATH
docker commit : Créer une nouvelle image à partir des changements d’un conteneur
docker cp : Copier des fichiers ou des dossiers depuis le PATH d’un conteneur vers le HOSTDIR ou vers STDOUT
docker create : Créer un nouveau conteneur
docker diff : Inspectez changements sur le système de fichiers d’un conteneur
docker events : Obtenir des événements en temps réel depuis le serveur
docker exec : Exécuter une commande dans le conteneur en cours d’exécution
docker export : Exporter le contenu d’un système de fichiers d’une archive tar vers STDOUT
docker history : Afficher l’historique d’une image Docker
docker images : Lister des images
docker import : Créer une image de système de fichiers vide et y importer le contenu d’une l’archive (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz), puis éventuellement y ajouter une étiquette (tag)
docker info : Afficher l’ensemble des informations système
docker inspect : Afficher les informations de bas niveau sur un conteneur ou une image Docker
docker kill : Tuer un conteneur en cours d’exécution en utilisant SIGKILL ou un signal spécifié
docker load : Chargez une image à partir d’une archive tar sur STDIN
docker login : Inscrivez-vous ou connectez-vous à le Docker Register (HUB)
docker logout : Déconnexion du Docker Register (HUB)
docker logs : Fetch des journaux d’un conteneur
docker pause : Mettre en pause tous les processus dans un conteneur
docker port : Liste les ports d’un conteneur, ou rechercher les ports “public” naté vers un PRIVATE_PORT
docker ps : Liste de conteneurs
docker pull : Récupérer une image ou un repository à partir du Docker HUB
docker push : Publier une image ou un repository vers le Docker HUB
docker rename : Renommer un conteneur Docker
docker restart : Redémarrez un conteneur en cours d’exécution
docker rm : Supprimer une ou plusieurs conteneurs
docker rmi : Supprimer une ou plusieurs images
docker run : Exécuter une commande dans un nouveau conteneur
docker save : Enregistrer une image dans une archive tar (streaming vers STDOUT par défaut)
docker search : Rechercher des images sur le Docker Hub
docker start : Lancer un ou plusieurs conteneurs arrêtés
docker stats : Afficher l’utilisation des ressources d’un ou plusieurs conteneurs sous la forme d’un flux
docker stop : Arrêtez un conteneur en cours d’exécution en envoyant SIGTERM et SIGKILL après une période de grâce
docker tag : Étiqueter une image dans un repository
docker top : Afficher les processus en cours d’exécution d’un conteneur
docker unpause : Réactiver tous les processus dans un conteneur
docker version : Afficher les informations de version Docker
docker wait : Bloquer jusqu’à l’arrêt du conteneur, puis imprime son code de sortie

6. Webographie

Wanadev

Le Blog Nicolargo