Est-il correct d'exécuter docker depuis l'intérieur de docker?

185

J'exécute Jenkins dans un conteneur Docker. Je me demande s'il est acceptable que le conteneur Jenkins soit également un hôte Docker? Ce à quoi je pense, c'est de démarrer un nouveau conteneur de docker pour chaque build de test d'intégration depuis Jenkins (pour démarrer des bases de données, des courtiers de messages, etc.). Les conteneurs doivent donc être arrêtés une fois les tests d'intégration terminés. Y a-t-il une raison d'éviter d'exécuter des conteneurs Docker à partir d'un autre conteneur Docker de cette manière?

Johan
la source
11
Une autre possibilité consiste à monter le socket docker à partir de l'hôte en tant que volume dans le conteneur. Cela vous permet de créer des conteneurs "frères" et présente l'avantage de pouvoir réutiliser le cache.
Adrian Mouat
4
J'ai constaté que lors de l'utilisation du socket docker de l'hôte, dans les cas où je veux monter des volumes externes, il est nécessaire de définir le chemin du volume par rapport à l'hôte car c'est là que le démon docker s'exécute. Le définir par rapport au conteneur qui démarre les conteneurs ne fonctionnera pas nécessairement à moins que les chemins ne coïncident.
Jakob Runge

Réponses:

224

L'exécution de Docker dans Docker (alias dind ), bien que possible, doit être évitée, dans la mesure du possible. (Source fournie ci-dessous.) Au lieu de cela, vous souhaitez configurer un moyen pour votre conteneur principal de produire et de communiquer avec des conteneurs frères .

Jérôme Petazzoni - l'auteur de la fonctionnalité qui a permis à Docker de s'exécuter dans un conteneur Docker - a en fait écrit un article de blog disant de ne pas le faire . Le cas d'utilisation qu'il décrit correspond au cas d'utilisation exact de l'OP d'un conteneur CI Docker qui doit exécuter des tâches dans d'autres conteneurs Docker.

Petazzoni énumère deux raisons pour lesquelles la dind est gênante:

  1. Il ne coopère pas bien avec les modules de sécurité Linux (LSM).
  2. Cela crée une incompatibilité dans les systèmes de fichiers qui crée des problèmes pour les conteneurs créés à l'intérieur des conteneurs parents.

À partir de ce billet de blog, il décrit l'alternative suivante,

[Le] moyen le plus simple est d'exposer simplement le socket Docker à votre conteneur CI, en le montant en liaison avec l' -vindicateur.

En termes simples, lorsque vous démarrez votre conteneur CI (Jenkins ou autre), au lieu de pirater quelque chose avec Docker-in-Docker, démarrez-le avec:

docker run -v /var/run/docker.sock:/var/run/docker.sock ...

Désormais, ce conteneur aura accès au socket Docker, et pourra donc démarrer des conteneurs. Sauf qu'au lieu de démarrer des conteneurs "enfants", il lancera des conteneurs "frères".

predmijat
la source
1
Comment exécuter des commandes docker sans sudofaire comme ça? Merci
c4k
3
Vous devez ajouter un utilisateur à un dockergroupe: sudo usermod -aG docker $USER. Vous devrez vous reconnecter après cela.
predmijat
2
Comment se reconnecter depuis un cointainer?
thiagowfx
1
@AlexanderMills Il en va de même car votre socket docker se trouve également là /var/run/docker.sockoù vous exécutez docker pour mac sur votre machine macos.
Bruce Sun
1
qu'en est-il des fenêtres? Je n'ai pas/var/run/docker.sock
Abdelhafid
54

J'ai déjà répondu à une question similaire sur la façon d'exécuter un conteneur Docker dans Docker .

Exécuter docker à l'intérieur de docker est certainement possible. L'essentiel est que vous ayez runle conteneur externe avec des privilèges supplémentaires (à commencer par --privileged=true), puis que vous installiez docker dans ce conteneur.

Consultez cet article de blog pour plus d'informations: Docker-in-Docker .

Un cas d'utilisation potentiel pour cela est décrit dans cette entrée . Le blog décrit comment créer des conteneurs Docker dans un conteneur Docker Jenkins.

Cependant, Docker dans Docker n'est pas l'approche recommandée pour résoudre ce type de problèmes. Au lieu de cela, l'approche recommandée consiste à créer des conteneurs «frères» comme décrit dans cet article

Ainsi, exécuter Docker dans Docker était par beaucoup considéré comme un bon type de solution pour ce type de problèmes. Maintenant, la tendance est d'utiliser des conteneurs "frères" à la place. Voir la réponse de @predmijat sur cette page pour plus d'informations.

Wassgren
la source
Voir le commentaire ci-dessous pour éviter le docker dans le docker.
Dan Poltawski
6

Il est possible d'exécuter Docker-in-Docker (DinD) et en fait Docker (la société) a une image DinD officielle pour cela.

La mise en garde cependant est qu'il nécessite un conteneur privilégié, qui en fonction de vos besoins de sécurité peut ne pas être une alternative viable.

La solution alternative d'exécuter Docker à l'aide de conteneurs frères (aka Docker-out-of-Docker ou DooD) ne nécessite pas de conteneur privilégié, mais présente quelques inconvénients qui découlent du fait que vous lancez le conteneur à partir d'un contexte qui est différent de celui dans lequel il s'exécute (c'est-à-dire que vous lancez le conteneur depuis un conteneur, mais il s'exécute au niveau de l'hôte, pas à l'intérieur du conteneur).

J'ai écrit un blog décrivant les avantages / inconvénients de DinD vs DooD ici .

Cela dit, Nestybox (une startup que je viens de fonder) travaille sur une solution qui exécute un véritable Docker-in-Docker en toute sécurité (sans utiliser de conteneurs privilégiés). Vous pouvez le consulter sur www.nestybox.com .

ctalledo
la source
0

Oui, nous pouvons exécuter docker dans le docker, nous devrons attacher le sockeet unix "/var/run/docker.sock" sur lequel le démon docker écoute par défaut en tant que volume le docker parent en utilisant "-v / var / run /docker.sock:/var/run/docker.sock ". Parfois, des problèmes de permissions peuvent survenir pour le socket du démon docker pour lequel vous pouvez écrire "sudo chmod 757 /var/run/docker.sock".

Et il faudrait également exécuter le docker en mode privilégié, de sorte que les commandes seraient:

sudo chmod 757 /var/run/docker.sock

docker run --privileged = true -v /var/run/docker.sock:/var/run/docker.sock -it ...

Renu Saini
la source