Outil indispensable à la gestion de vos stack Docker, Docker Compose est très fortement utilisé par la communauté. Je l'utilise moi même au quotidien, mais avec un nombre toujours croissant de serveurs à gérer, la commande commence à trouver ses limites !
Car aujourd'hui peu de solutions s'offrent à nous afin de déployer facilement des ensembles de services sur des hôtes distants. Quelles solutions avons-nous pour déployer des applications on remote ?
Ansible ? Puppet ? Une pipeline CI/CD ? Ces outils sont formidables pour automatiser des déploiements connus et maîtrisés. Mais de façon plus pragmatique, ils ajoutent également une couche de complexité dont je n'ai pas forcément besoin afin de réaliser mes démos ou de livrer facilement en production une nouvelle stack oneshot.
Initialement prévu pour s'exécuter sur un moteur Docker présent localement, la commande Docker Compose ne répond pas encore à ce besoin. Mais la commande commence à évoluer et la prochaine version 1.26, qui est actuellement en release candidate apporte quelques réponses !! Qu'apporte cette version afin de répondre à ce besoin ?
La copie de fichiers ...
Avant d'aborder les nouveautés, un constat sur la méthodologie utilisée par beaucoup d'entre nous pour déployer des services conteneurisés sur des hôtes distants.
Une utilisation courante de Compose consiste à copier la source du projet, avec votre fichier docker-compose.yml
, sur la machine distante et d'y installer la commande.
Que vous utilisiez scp
, rsync
ou git
, peu importe. La manipulation fonctionne sans aucun soucis, exemple ici :
$ ssh user@remotehost
$ git clone myrepo
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ cd myrepo
$ docker-compose up -d
Mais dans certains cas cette façon de procéder peut devenir problématique. Effectivement, il va falloir installer docker-compose sur toutes vos machines et maintenir l'exécutable à jour si vous souhaitez utiliser les dernières fonctionnalités.
Et je ne vais pas aborder la question de la sécurité de vos projets. Généralement les fichiers contiennent des éléments sensibles, mot de passe de base de données, clé API, etc ... Vous les effacez de vos serveurs après le déploiement ?
À noter également que cette manipulation peut parfois créer quelques soucis de versionning dans vos fichiers docker-compose.yml
. Est-ce que j'ai bien récupéré le dernier fichier modifié directement sur la production !? ( Oui oui on a tous déjà fait une manipulation de ce type 😂 )
Pour des environnements ou le nombre de serveurs à manipuler est peu conséquent, cette utilisation est simple et efficace. Mais si votre parc est bien plus important... Cette méthodologie va vite devenir un casse-tête. D'autres solutions ?!
Docker Compose 1.26
Alors qu'ajoute cette version de Compose qui me pousse à vous écrire un article rien qu'à ce sujet ?Et bien cette version ajoute notamment :
- Add v3.8 schema support
Mais nous aurons sûrement l'occasion de revenir là-dessus plus tard 😀
Pour le moment, ce qui m'intéresse :
- Add docker context support
Aucun commentaire :
J'ai pu évoquer l'utilisation des context Docker très récemment sur le blog. Prenez le temps de lire l'article présent ici, car vous allez très rapidement comprendre tout l'intérêt de cette notion :
Moi je pars installer cette nouvelle version immédiatement !
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.0-rc3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Et on rend tout ça exécutable :
sudo chmod +x /usr/local/bin/docker-compose
Vérifiez immédiatement votre version :
docker-compose --version
docker-compose version 1.26.0-rc3, build 46118bc5
Les context
Rappelons tout de même rapidement :
Un context Docker est un mécanisme qui permet de fournir des noms aux endpoints de l'API Docker et de stocker ces informations pour une utilisation ultérieure. Les contexts Docker peuvent être facilement gérés avec la CLI Docker.
Assurez-vous bien évidement d'avoir mis en place des clés SSH sur votre machine distante. Il est également nécessaire que l'utilisateur cible est accès au groupe Docker.
Dans un premier temps, il va donc falloir créer un context afin de pouvoir utiliser ce endpoint ultérieurement :
docker context create dev --docker host=ssh://[email protected] --default-stack-orchestrator=swarm
🚩 Même si votre serveur n'est pas un cluster Swarm, à date, la commande ne fonctionne pas si je ne précise pas l'orchestrateur. Aucune incidence pour un node Docker simple. 🚩
Vous pouvez vérifier la création de votre context avec la commande suivante :
docker context ls
Je vais maintenant créer un fichier docker-compose.yml
d'exemple :
version: "3.7"
services:
frontend:
image: traefik:2.2
command: --providers.docker --entrypoints.web.address=:80 --providers.docker.exposedbydefault=false
ports:
# The HTTP port
- "80:80"
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- backend
backend:
image: containous/whoami
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Path(`/`)"
- "traefik.http.services.whoami.loadbalancer.server.port=80"
Oui oui, par hasard j'utilise une image Traefik et whoami 😄
Il me reste plus qu'à déployer cette stack dans mon context. J'ai deux possibilités pour réaliser ça :
docker-compose --context dev up -d
🚩 Sans le flag -d
, vous allez avoir un retour d'erreur. La commande ne permet pas de garder la main sur le conteneur lancé. Logique mais aussi frustrant parfois ! 🚩
Je vais vérifier que tout est lancé :
docker --context dev ps
Et aussi :
curl http://X.X.X.X/
Hostname: 205f75ae1962
IP: 127.0.0.1
IP: 172.19.0.2
RemoteAddr: 172.19.0.3:46222
GET / HTTP/1.1
Host: X.X.X.X
User-Agent: curl/7.68.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: X.X.X.X
X-Forwarded-Host: X.X.X.X
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: c3c5cf6e4f02
X-Real-Ip: X.X.X.X
Nous pouvons arrêter la stack :
docker-compose --context dev down
De mon côté, j'ai une erreur pour le moment lors de l'arrêt de la stack mais tout semble fonctionner correctement :
ERROR: for lfache_frontend_1 ChannelException(2, 'Connect failed')
Traceback (most recent call last):
File "bin/docker-compose", line 6, in <module>
File "compose/cli/main.py", line 72, in main
File "compose/cli/main.py", line 128, in perform_command
File "compose/cli/main.py", line 424, in down
File "compose/project.py", line 340, in down
File "compose/project.py", line 328, in remove_stopped
File "compose/parallel.py", line 341, in parallel_remove
File "compose/parallel.py", line 335, in parallel_operation
File "compose/parallel.py", line 112, in parallel_execute
File "compose/parallel.py", line 210, in producer
File "compose/container.py", line 259, in remove
File "site-packages/docker/utils/decorators.py", line 19, in wrapped
File "site-packages/docker/api/container.py", line 994, in remove_container
File "site-packages/docker/utils/decorators.py", line 46, in inner
File "site-packages/docker/api/client.py", line 238, in _delete
File "site-packages/requests/sessions.py", line 615, in delete
File "site-packages/requests/sessions.py", line 533, in request
File "site-packages/requests/sessions.py", line 646, in send
File "site-packages/requests/adapters.py", line 449, in send
File "site-packages/urllib3/connectionpool.py", line 672, in urlopen
File "site-packages/urllib3/connectionpool.py", line 387, in _make_request
File "http/client.py", line 1252, in request
File "http/client.py", line 1298, in _send_request
File "http/client.py", line 1247, in endheaders
File "http/client.py", line 1026, in _send_output
File "http/client.py", line 966, in send
File "site-packages/docker/transport/sshconn.py", line 32, in connect
File "site-packages/paramiko/transport.py", line 879, in open_session
File "site-packages/paramiko/transport.py", line 1017, in open_channel
paramiko.ssh_exception.ChannelException: ChannelException(2, 'Connect failed')
[20604] Failed to execute script docker-compose
docker --context dev ps
ne renvoie aucun conteneur actif. Le down
semble donc fonctionner correctement.
J'ai parlé de deux méthodes, car il n'est pas forcément nécessaire de préciser votre context systématiquement.
Vous pouvez changer celui par défaut afin que docker-compose l'utilise. Rien de plus simple :
docker context use dev
Dans ces conditions, la commande docker-compose fonctionne comme d'habitude !
Vous avez pu voir au cours de l'article comment déployer vos stacks sur des serveurs distants, sans aucune copie de fichier avec l'utilisation de la nouvelle version de la commande Docker Compose.
Je trouve que la combinaison de docker context
et docker-compose --context
est vraiment formidable et va faciliter le déploiment d'instance et de conteneur dans bien des cas !
Cet article vous a t-il donné envie d'essayer cette nouveauté ? En tout cas de mon côté, je n'en ai pas fini avec les context. Prochain cas d'utilisation avec ... Docker Swarm ! Nous verrons ça ensemble au prochain épisode 😀
En tout cas n'hésitez pas à m'apporter des remarques ou des commentaires sur Twitter ! C'est toujours un plaisir d'avoir des retours ! 😇