Comment exécuter plusieurs services dans un conteneur Docker
Agence web » Actualités du digital » Comment exécuter plusieurs services dans un conteneur Docker

Comment exécuter plusieurs services dans un conteneur Docker

Docker est une technologie permettant d’emballer les composants de votre pile sous forme de conteneurs isolés. Il est courant d’exécuter chacun de vos processus dans son propre conteneur, créant ainsi une séparation nette entre les composants. Cela améliore la modularité et vous permet d’accéder aux avantages d’évolutivité de la conteneurisation.

Il peut toujours y avoir des situations où vous souhaitez exécuter plusieurs services dans un même conteneur. Bien que cela ne soit pas naturel dans l’écosystème Docker, nous allons montrer quelques approches différentes que vous pouvez utiliser pour créer des conteneurs avec plusieurs processus de longue durée.

Identification du problème

Les conteneurs Docker exécutent un seul processus de premier plan. Ceci est défini par l’image ENTRYPOINT et CMD des instructions. ENTRYPOINT est défini dans une image Dockerfile tandis que CMD peut être remplacé lors de la création de conteneurs. Les conteneurs s’arrêtent automatiquement lorsque leur processus de premier plan se termine.

Vous pouvez lancer d’autres processus à partir du CMD mais le conteneur ne restera en cours d’exécution que tant que le processus de premier plan d’origine est actif. Maintenir le conteneur opérationnel pendant la durée de vie combinée de deux services indépendants n’est pas directement possible en utilisant le ENTRYPOINT/CMD mécanisme.

Envelopper plusieurs processus dans un seul point d’entrée

Les scripts wrapper sont la solution la plus simple au problème. Vous pouvez écrire un script qui démarre tous vos processus et attend qu’ils se terminent. Définir le script comme votre Docker ENTRYPOINT l’exécutera en tant que processus de premier plan du conteneur, en gardant le conteneur en cours d’exécution jusqu’à ce que l’un des scripts encapsulés se termine.

#!/bin/bash

/opt/first-process &

/opt/second-process &

wait -n

exit $?

Ce script lance le /opt/first-process et /opt/second-process binaires à l’intérieur du conteneur. L’utilisation de & permet au script de continuer sans attendre la fin de chaque processus. wait est utilisé pour suspendre le script jusqu’à ce que l’un des processus se termine. Le script se termine ensuite avec le code d’état émis par le script terminé.

Ce modèle permet au conteneur d’exécuter à la fois first-process et second-process jusqu’à ce que l’un d’eux sorte. À ce stade, le conteneur s’arrêtera, même si l’autre processus est toujours en cours d’exécution.

Pour utiliser ce script, modifiez votre image Docker ENTRYPOINT et CMD pour en faire le processus de premier plan du conteneur :

ENTRYPOINT ["/bin/sh"]
CMD ["./path/to/script.sh"]

La --init Option de conteneur

L’un des défis de la gestion des processus de conteneurs consiste à nettoyer efficacement à leur sortie. Docker exécute votre CMD en tant que processus ID 1, ce qui le rend responsable de la gestion des signaux et de l’élimination des zombies. Si votre script ne dispose pas de ces fonctionnalités, vous pourriez vous retrouver avec des processus enfants orphelins persistants dans votre conteneur.

La docker run la commande a un --init drapeau qui modifie le point d’entrée à utiliser tini comme PID 1. Il s’agit d’une implémentation minimale du processus d’initialisation qui exécute votre CMDgère la transmission du signal et récolte continuellement des zombies.

Cela vaut la peine d’utiliser --init si vous vous attendez à générer de nombreux processus et que vous ne souhaitez pas gérer manuellement le nettoyage. Tini est une saveur init légère conçue pour les conteneurs. C’est beaucoup plus petit que des alternatives à part entière comme systemd et upstart.

Utiliser un gestionnaire de processus dédié

Les scripts manuels deviennent rapidement sous-optimaux lorsque vous avez de nombreux processus à gérer. Adopter un gestionnaire de processus est une autre façon d’exécuter plusieurs services dans vos conteneurs Docker. Le gestionnaire de processus devient votre ENTRYPOINT et est responsable du démarrage, de la maintenance et du nettoyage après vos processus de travail.

Plusieurs options sont disponibles lors de la mise en œuvre de cette approche. supervisord est un choix populaire qui est facilement configuré via un /etc/supervisor/conf.d/supervisord.conf dossier:

[program:apache2]
command=/usr/sbin/apache2 -DFOREGROUND

[program:mysqld]
command=/usr/sbin/mysqld_safe

Ce fichier de configuration configure supervisord pour démarrer Apache et MySQL. Pour l’utiliser dans un conteneur Docker, ajoutez tous les packages requis à votre image, puis copiez votre supervisord fichier de configuration à l’emplacement correct. Régler supervisord comme l’image CMD pour l’exécuter automatiquement au démarrage des conteneurs.

FROM ubuntu:latest
RUN apt-get install -y apache2 mysql-server supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
ENTRYPOINT ["/bin/sh"]
CMD ["/usr/bin/supervisord"]

Car supervisord s’exécute en continu, il n’est pas possible d’arrêter le conteneur lorsque l’un de vos processus surveillés se termine. Une option alternative est s6-overlay qui a cette capacité. Il utilise un modèle de service déclaratif dans lequel vous placez des scripts de service directement dans /etc/services.d:

# Add s6-overlay to your image
ADD https://github.com/just-containers/s6-overlay/releases/download/v3.1.0.0/s6-overlay-noarch.tar.xz /tmp
RUN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz

RUN printf "#!/bin/shn/usr/sbin/apache2 -DFOREGROUND" > /etc/services.d/first-service/run
RUN chmod +x /etc/services.d/first-service/run

# Use s6-overlay as your image's entrypoint
ENTRYPOINT ["/init"]

Vous pouvez ajouter un exécutable finish script dans vos répertoires de service pour gérer l’arrêt du conteneur avec docker stop. s6-overlay exécutera automatiquement ces scripts lorsque son processus recevra un TERM signal en raison de la stop commande.

Les scripts de finition reçoivent le code de sortie de leur service comme premier argument. Le code est défini sur 256 lorsque le service est interrompu en raison d’un signal non capté. Le script doit écrire le code de sortie final pour /run/s6-linux-init-container-results/exitcode; s6-overlay lit ce fichier et se termine avec la valeur qu’il contient, ce qui fait que ce code est utilisé comme code d’arrêt de votre conteneur.

#!/bin/sh
echo "$1" > /run/s6-linux-init-container-results/exitcode

Quand devez-vous exécuter plusieurs processus dans un conteneur ?

Cette technique est mieux utilisée avec des processus étroitement couplés que vous ne pouvez pas séparer pour les exécuter en tant que conteneurs indépendants. Vous pouvez avoir un programme qui s’appuie sur un utilitaire d’assistance en arrière-plan ou une application monolithique qui effectue sa propre gestion des processus individuels. Les techniques présentées ci-dessus peuvent vous aider à conteneuriser ces types de logiciels.

L’exécution de plusieurs processus dans un conteneur doit toujours être évitée dans la mesure du possible. S’en tenir à un seul processus de premier plan maximise l’isolation, empêche les composants d’interférer les uns avec les autres et améliore votre capacité à déboguer et tester des éléments spécifiques. Vous pouvez mettre à l’échelle les composants individuellement à l’aide d’orchestrateurs de conteneurs, ce qui vous donne la possibilité d’exécuter davantage d’instances de vos processus les plus gourmands en ressources.

Conclusion

Les conteneurs ont généralement un processus de premier plan et s’exécutent aussi longtemps qu’il est actif. Ce modèle s’aligne sur les meilleures pratiques de conteneurisation et vous permet de tirer le meilleur parti de la technologie.

Dans certaines situations, vous pouvez avoir besoin de plusieurs processus pour s’exécuter dans un conteneur. Comme toutes les images ont finalement un seul point d’entrée, vous devez écrire un script wrapper ou ajouter un gestionnaire de processus qui prend la responsabilité de démarrer vos binaires cibles.

Les gestionnaires de processus vous donnent tout ce dont vous avez besoin, mais gonflent vos images avec des packages et une configuration supplémentaires. Les scripts wrapper sont plus simples mais peuvent devoir être associés à Docker --init drapeau pour empêcher la prolifération des processus zombies.

★★★★★