Parmi toutes les fonctionnalités disponibles, il en est une qui explique pour beaucoup le dynamisme phénoménal de l’écosystème Docker. Il s’agit de Docker Remote API, une API REST extrêmement bien conçue exposant toutes les fonctionnalités du moteur Docker et permettant ainsi de piloter un hôte Docker depuis une machine ou une application distante.
Toutes les solutions d’orchestration de conteneurs Docker utilisent directement ou indirectement l’API Docker Remote, raison pour laquelle je vous propose d’y jeter un oeil attentif.
Dans cet article, nous verrons :
- comment fonctionne l’interaction avec le démon Docker
- comment activer Docker Remote API avec et sans certificats TLS
- comment utiliser Docker Machine avec un hôte Docker déjà provisionné sur un réseau local d’entreprise
La communication avec le démon Docker
Le schéma ci-dessous représente l’architecture type d’un serveur Linux (sous Ubuntu) hébergeant un hôte Docker. Le moteur Docker (serveur) est un démon écoutant par défaut sur un socket UNIX (/var/run/docker.sock
).
Pour mémoire, les sockets UNIX permettent à deux ou plusieurs processus d’échanger des données de façon bi-directionnelle.
Ainsi, le client Docker installé localement interagit avec le démon via le socket UNIX /var/run/docker.sock
. Sans surprise, le protocole d’échange utilisé par l’API Docker est de type REST comme nous allons le voir ci-après.
Exécutons par exemple la commande GET /info
, permettant d’obtenir des informations système de l’hôte Docker.
Pour ce faire, j’utilise l’utilitaire Netcat (commande nc
) afin d’envoyer la requête au socket /var/run/docker.sock
:
Voici un extrait de la réponse obtenue :
On remarquera que le corps de la réponse est au format JSON.
Maintenant, voyons à quoi ressemblerait une combinaison associant :
- un hôte Docker avec activation de Docker Remote API
- un client Docker localisé sur une machine distante
Voyons comment activer et utiliser Docker Remote API avec et sans certificats TLS.
Activer Docker Remote API sans certificat TLS
Cette configuration n’est pas recommandée en production car la communication entre client et hôte Docker est en clair. Elle est néanmoins fort utile à des fins de test. Voici comment la mettre en oeuvre :
Côté serveur (orion.local
sous Ubuntu) :
- éditer le fichier
/etc/default/docker
puis renseigner la variable d’environnementDOCKER_OPTS
comme suit :
DOCKER_OPTS="-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"
- redémarrer le démon docker :
**ksahnine@orion:~$** sudo service docker restart
A ce stade, le démon écoute sur le port TCP 2375
ainsi que sur le socket UNIX /var/run/docker.sock
.
Note : Le fichier
/etc/default/docker
n’est présent que sous Ubuntu. A défaut, il faudra renseigner et exporter la variable d’environnementDOCKER_OPTS
.
Côté client (laptop.local
) :
- pour interroger l’hôte Docker depuis une autre machine, utiliser la commande docker en renseignant l’option
-H
avec l’adresse et le port d’écoute de l’hôte Docker distant.
L’exemple ci-dessous permet d’afficher la liste des conteneurs actifs sur l’hôte Docker distant :
ksahnine@laptop:~$ docker -H=192.168.0.29:2375 ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6faede9c46af nginx:latest “nginx -g ‘daemon of 12 minutes ago Up 12 minutes 80/tcp, 443/tcp sleepy_lalande
Note : On peut aussi renseigner la variable d’environnement
DOCKER_HOST
sur le poste client (export DOCKER_HOST=192.168.0.29:2375
) et lancer tout simplement la commandedocker ps
sans l’option-H
A l’aide de tcpdump
, interceptons les échanges entre le client Docker et l’hôte Docker distant :
On remarquera que la requête issue de la commande docker ps
est la suivante :
On pourrait donc se passer du client Docker et utiliser directement l’utilitaire cURL, dont la commande équivalente à docker ps
serait :
Activer Docker Remote API avec certificat TLS
Il nous faut tout d’abord produire 3 certificats :
- le certificat racine utilisé comme autorité de certification. Il sera utilisé pour signer les certificats client et serveur.
- le certificat serveur installé et utilisé par l’hôte Docker
- le certificat client installé et utilisé par le client Docker
Je mets à disposition un script shell permettant de générer les certificats de test et dont voici le mode opératoire d’utilisation correspondant à notre cas :
**ksahnine@orion:~$** wget https://raw.githubusercontent.com/ksahnine/docker/master/gen-docker-certs.sh **ksahnine@orion:~$** sh gen-docker-certs.sh - Nom de l’hôte Docker : orion - Adresse IP de l’hôte Docker : 192.168.0.29
Le script produit :
- le certificat racine (clé publique
ca.pem
) - le certificat client (clé publique
cert.pem
/ clé privéekey.pem
) - le certificat serveur (clé publique
server.pem
/ clé privéeserver-key.pem
)
Passons à la configuration du serveur et du client Docker.
Côté serveur (orion.local
sous Ubuntu) :
- copier les fichier
ca.pem
,server.pem
etserver-key.pem
dans le répertoire/root/.docker
(ou tout autre répertoire sécurisé) - éditer le fichier
/etc/default/docker
puis renseigner la variable d’environnementDOCKER_OPTS
comme suit :
DOCKER_OPTS="--tlsverify --tlscacert=/root/.docker/ca.pem --tlscert=/root/.docker/server.pem \\ --tlskey=/root/.docker/server-key.pem -H=unix:///var/run/docker.sock -H=0.0.0.0:2376"
- redémarrer le démon docker :
**ksahnine@orion:~$** sudo service docker restart
A ce stade, le démon écoute sur le socket UNIX /var/run/docker.sock
ainsi que sur le port TCP 2376
, port utilisé par convention pour les échanges sécurisés.
Côté client (laptop.local
) :
- copier les fichiers
ca.pem
,cert.pem
etkey.pem
dans le répertoire~/.docker
- utiliser la commande
docker
avec le flag--tlsverify
pour passer en mode TLS.
L’exemple ci-dessous permet d’afficher la liste des conteneurs actifs sur l’hôte Docker distant :
**ksahnine@laptop:~$** docker –tlsverify -H=192.168.0.29:2376 ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6faede9c46af nginx:latest “nginx -g ‘daemon of 12 minutes ago Up 12 minutes 80/tcp, 443/tcp sleepy_lalande
Note : Vous avez noté que je n’ai pas passé explicitement les clés dans la ligne de commande. Par défaut, le client docker s’attend à trouver le certificat racine sous
~/.docker/ca.pem
, le certificat client sous~/.docker/cert.pem
et la clé privée sous~/.docker/key.pem
. Si les noms des clés diffèrent ou s’ils sont localisés dans un autre répertoire, il faudra utiliser respectivement les options--tlscacert
,--tlscert
et--tlskey
. Le flag--tlsverify
peut être omis si la variable d’environnementDOCKER_TLS_VERIFY
est valorisée à1
.
Utilisation avec Docker Machine
Si vous gérez plusieurs hôtes Docker répartis sur un LAN et/ou dans un cloud public, il est beaucoup plus pratique de travailler avec Docker Machine depuis un simple ordinateur portable.
Dans le cas de cet article, un hôte Docker est déjà provisionné sur le serveur Linux orion.local
(192.168.0.29
).
Rajoutons l’hôte sous le nom orionbox
:
**ksahnine@laptop:~$** docker-machine create –driver none –url=tcp://192.168.0.29:2376 orionbox
La commande docker-machine ls
le confirme :
**ksahnine@laptop:~$** docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM orionbox * none tcp://192.168.0.29:2376
Copier les certificats client, serveur et racine précédemment générés (fichiers ca.pem
, cert.pem
, key.pem
, server.pem
et server-key.pem
) dans le répertoire ~/.docker/machine/machines/orionbox
.
La commande docker-machine env
affiche les variables d’environnement à positionner pour forcer le client docker à interagir avec une machine particulière, orionbox
dans notre cas :
Note : Remarquez l’erreur d’exécution obtenue en sortie. A ma connaissance, l’utilisation de l’option
--driver none
ne permet pas de configurer d’authentification par clés SSH afin que Docker Machine puisse exécuter des commandes à distance. A ce jour, Docker Machine est encore en version bêta (v 0.20). Sauf erreur de ma part, il faudra attendre la publication du driver generic actuellement en cours de développement. Il devrait permettre de provisionner un hôte Docker sur n’importe quel serveur existant accessible par SSH, un peu à la manière d’Ansible.
Mise à jour 29/06/2015 : Le driver
generic
est désormais disponible depuis la version 0.3 de Docker Machine.
Passons outre le message d’erreur et positionnons les variables d’environnements comme suit :
ou plus simplement :
C’est terminé. Notre client Docker est configuré pour interagir avec l’hôte docker distant.