Docker in Docker (dind) avec Docker

1 - Docker in Docker (dind)

Il est parfois nécessaire d'exécuter des commandes Docker à l'intérieur d'un conteneur, par exemple pour lancer des builds d'images depuis un conteneur Jenkins. Installer Docker directement dans chaque conteneur alourdirait inutilement l'image. Une meilleure approche consiste à déployer uniquement le client Docker (l'interface en ligne de commande) dans le conteneur, tandis que l'exécution réelle est confiée au moteur Docker (docker-engine) de l'hôte.

2 - Deux appproches

Il existe deux manières d'utiliser Docker dans un conteneur tout en bénéficiant des avantages de l'isolation et de la légèreté.

2.1 Via le socket Docker de l'hôte

En montant le socket Docker de l'hôte (/var/run/docker.sock) et le binaire /usr/bin/docker dans le conteneur avec une commande comme docker run -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker, le conteneur peut envoquer le démon Docker de l'hôte sans exécuter lui-même un serveur Docker. Cela permet une version légère de Docker in Docker, même si techniquement ce n'est pas un véritable "Docker in Docker" puisque le serveur Docker reste sur l'hôte.

2.2 Via l'image docker:dind

On démarre d'abord un conteneur A utilisant l'image officielle docker:dind (Docker in Docker), puis un conteneur B qui utilise le démon Docker du conteneur A en spécifiant l'hôte approprié. Cette méthode isole complètement l'environnement Docker du conteneur B tout en restant autonome.

3 - Exemple : Exécuter Jenkins via Docker Desktop sur Windows

Cet exemple est basé sur la documentation officilele de Jenkins : https://www.jenkins.io/doc/book/installing/

Étapes pour lancer Jenkins avec un moteur Docker embarqué (dind) :

# Créer un réseau Docker dédié
docker network create jenkins

# Créer les volumes pour les certificats et les données Jenkins
docker volume create jenkins-docker-certs
docker volume create jenkins-data

# Lancer le conteneur Docker in Docker (dind)
docker container run --name jenkins-docker --detach \
  --privileged --network jenkins --network-alias docker \
  --env DOCKER_TLS_CERTDIR=/certs \
  --volume jenkins-docker-certs:/certs/client \
  --volume jenkins-data:/var/jenkins_home \
  docker:dind

# Lancer le conteneur Jenkins BlueOcean
docker container run --name jenkins-blueocean --detach \
  --network jenkins \
  --env DOCKER_HOST=tcp://docker:2376 \
  --env DOCKER_CERT_PATH=/certs/client \
  --env DOCKER_TLS_VERIFY=1 \
  --volume jenkins-data:/var/jenkins_home \
  --volume jenkins-docker-certs:/certs/client:ro \
  --publish 8080:8080 \
  --publish 50000:50000 \
  jenkinsci/blueocean

Après le démarrage, récupérez le mot de passe initial de Jenkins :

docker exec jenkins-blueocean cat /var/jenkins_home/secrets/initialAdminPassword

Exemple de sortie : b22f3b04344f4094bb6b26e1312002e8

4 - Liste des commandes essentielles

Voici un récapitulatif des commandes utilisées dans cet exemple :

# Réseau
docker network create jenkins

# Volumes
docker volume create jenkins-docker-certs
docker volume create jenkins-data

# Conteneur dind
docker container run \
  --name jenkins-docker \
  --detach \
  --privileged \
  --network jenkins \
  --network-alias docker \
  --env DOCKER_TLS_CERTDIR=/certs \
  --volume jenkins-docker-certs:/certs/client \
  --volume jenkins-data:/var/jenkins_home \
  docker:dind

# Conteneur Jenkins
docker container run \
  --name jenkins-blueocean \
  --detach \
  --network jenkins \
  --env DOCKER_HOST=tcp://docker:2376 \
  --env DOCKER_CERT_PATH=/certs/client \
  --env DOCKER_TLS_VERIFY=1 \
  --volume jenkins-data:/var/jenkins_home \
  --volume jenkins-docker-certs:/certs/client:ro \
  --publish 8080:8080 \
  --publish 50000:50000 \
  jenkinsci/blueocean

Étiquettes: Docker docker-in-docker containers devops Jenkins

Publié le 6 juillet à 19h24