Salut tout le monde! Dans son
début
Tout a commencé un soir pluvieux de septembre alors que je nettoyais la machine que j'avais louée pour 5 $ sur Digital Ocean, qui était gelée car Docker avait rempli les 24 Go d'espace disque disponible avec ses images et ses conteneurs. L'ironie était que toutes ces images et conteneurs étaient éphémères et n'étaient nécessaires que pour tester les performances de mon application à chaque fois qu'une nouvelle version d'une bibliothèque ou d'un framework était publiée. J'ai essayé d'écrire des scripts shell et de mettre en place une planification cron pour nettoyer les déchets, mais cela n'a pas aidé : à chaque fois, cela se terminait inévitablement par une consommation d'espace disque de mon serveur et une suspension du serveur (au mieux). À un moment donné, je suis tombé sur un article sur la façon d'exécuter Jenkins dans un conteneur et comment il peut créer et supprimer des pipelines de construction via un socket de démon Docker qui y est transféré. J'ai aimé l'idée, mais j'ai décidé d'aller plus loin et d'essayer d'expérimenter l'exécution directe de Docker dans Docker. À cette époque, il me semblait une solution tout à fait logique de télécharger des images Docker et de créer des conteneurs pour toutes les applications dont j'avais besoin pour tester dans un autre conteneur (appelons-le un conteneur intermédiaire). L'idée était de démarrer un conteneur intermédiaire avec l'indicateur -rm, qui supprime automatiquement l'intégralité du conteneur et tout son contenu lorsqu'il est arrêté. J'ai bricolé l'image Docker de Docker lui-même (
Pratique. Cônes
J'ai décidé de faire fonctionner le conteneur comme j'en avais besoin et j'ai continué mes expériences, qui ont abouti à une myriade de têtes. Le résultat de mon auto-torture était l’algorithme suivant :
-
Nous lançons le conteneur Docker en mode interactif.
docker run --privileged -it docker:18.09.6
Faites attention à la version du conteneur, avancez à droite ou à gauche et votre DinD se transforme en citrouille. En fait, les choses se cassent assez souvent lorsqu'une nouvelle version sort.
Il faut immédiatement rentrer dans la coquille. -
Nous essayons de savoir quels conteneurs sont en cours d'exécution (Réponse : aucun), mais exécutons quand même la commande :
docker ps
Vous serez un peu surpris, mais il s'avère que le démon Docker ne fonctionne même pas :
error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 192.168.65.1:53: no such host
-
Exécutons-le nous-mêmes :
dockerd &
Autre mauvaise surprise :
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not found
-
Installez les packages iptables et bash (tout est plus agréable à travailler en bash qu'en sh) :
apk add --no-cache iptables bash
-
Lançons bash. Enfin nous sommes de retour dans la coquille habituelle
-
Essayons d'exécuter à nouveau Docker :
dockerd &
Nous devrions voir une longue feuille de logs se terminant par :
INFO[2019-11-25T19:51:19.448080400Z] Daemon has completed initialization INFO[2019-11-25T19:51:19.474439300Z] API listen on /var/run/docker.sock
-
Appuyez sur Entrée. Nous sommes de retour à la fête.
À partir de maintenant, nous pouvons essayer de lancer d'autres conteneurs à l'intérieur de notre conteneur Docker, mais que se passe-t-il si nous voulons lancer un autre conteneur Docker à l'intérieur de notre conteneur Docker ou si quelque chose ne va pas et que le conteneur plante ? Recommencer à zéro.
Propre conteneur DinD et nouvelles expériences
Pour éviter de répéter encore et encore les étapes ci-dessus, j'ai créé mon propre conteneur DinD :
La solution DinD fonctionnelle m'a donné la possibilité d'exécuter Docker dans Docker de manière récursive et de faire des expériences plus aventureuses.
Je vais maintenant décrire une de ces expériences (réussies) avec l'exécution de MySQL et Nodejs.
Les plus impatients peuvent voir comment ça s'est passé ici
Commençons donc:
-
Nous lançons DinD en mode interactif. Dans cette version de DinD, nous devons mapper manuellement tous les ports que nos conteneurs enfants peuvent utiliser (je travaille déjà là-dessus)
docker run --privileged -it -p 80:8080 -p 3306:3306 alekslitvinenk/dind
Nous entrons dans la fête, d'où nous pouvons immédiatement commencer à lancer des conteneurs enfants.
-
Lancez MySQL :
docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql
-
Nous nous connectons à la base de données de la même manière que nous nous y connecterions localement. Assurons-nous que tout fonctionne.
-
Lancez le deuxième conteneur :
docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server
Veuillez noter que le mappage des ports sera exactement 8080:8080, puisque nous avons déjà mappé le port 80 de l'hôte vers le conteneur parent vers le port 8080.
-
Nous allons sur localhost dans le navigateur, assurez-vous que le serveur répond « Hello World ! »
Dans mon cas, l'expérience avec les conteneurs Docker imbriqués s'est avérée plutôt positive et je continuerai à développer le projet et à l'utiliser pour la mise en scène. Il me semble que c'est une solution beaucoup plus légère que Kubernetes et Jenkins X. Mais c'est mon opinion subjective.
Je pense que c'est tout pour l'article d'aujourd'hui. Dans le prochain article, je décrirai plus en détail des expériences d'exécution récursive de Docker dans Docker et de montage de répertoires profondément dans des conteneurs imbriqués.
PS Si vous trouvez ce projet utile, donnez-lui une étoile sur GitHub, partagez-le et parlez-en à vos amis.
Edit1 Erreurs corrigées, concentrées sur 2 vidéos
Source: habr.com