Cómo lancé Docker dentro de Docker y qué surgió

Hola a todos! En mi artículo anterior , prometí hablar sobre el lanzamiento de Docker en Docker y los aspectos prácticos de la aplicación de esta lección. Es hora de cumplir nuestra promesa. Un devodor experimentado, tal vez, argumentaría que aquellos que necesitan Docker dentro de Docker simplemente arrojan el zócalo del demonio Docker desde el host dentro del contenedor y esto es suficiente en el 99% de los casos. Pero no te apresures a arrojarme galletas, porque hablaremos sobre el lanzamiento real de Docker dentro de Docker. Esta solución tiene muchos campos de aplicación posibles y este artículo trata sobre uno de ellos, así que siéntese y estire los brazos frente a usted.


imagen

Inicio


Todo comenzó en una lluviosa tarde de septiembre cuando estaba limpiando un auto de alquiler de Digital Ocean por $ 5, que colgaba muy apretado porque Docker llenó los 24 gigabytes de espacio disponible en disco con sus imágenes y contenedores. La ironía era que todas estas imágenes y contenedores eran transitorios y solo se necesitaban para probar el rendimiento de mi aplicación cada vez que salía una nueva versión de una biblioteca o marco. Traté de escribir scripts de shell y configurar el calendario de coronas para la limpieza de basura, pero esto no se guardó: cada vez, inevitablemente, el espacio en disco de mi servidor se agotaba y el servidor se bloqueaba (en el mejor de los casos). En algún momento, me encontré con un artículo sobre cómo ejecutar Jenkins en un contenedor y cómo puede crear y eliminar tuberías de ensamblaje a través del zócalo Doemon Daemon. Me gustó la idea, pero decidí seguir adelante e intentar experimentar con el lanzamiento directo de Docker dentro de Docker. Entonces me pareció una decisión completamente lógica bombear imágenes de la ventana acoplable y crear contenedores de todas las aplicaciones que necesito para probar dentro de otro contenedor (llamémoslo un contenedor provisional). La idea era ejecutar un contenedor provisional con el indicador -rm, que elimina automáticamente todo el contenedor con todo su contenido cuando se detiene. Rebusqué con la imagen de la ventana acoplable de la propia ventana acoplable ( https://hub.docker.com/_/docker ), pero resultó ser demasiado voluminosa y no pude hacer que funcionara como lo necesitaba y quería hacerlo todo el tiempo.


Practica Golpes


Me propuse hacer que el contenedor funcionara como lo necesitaba y continué mis experimentos, lo que resultó en una gran cantidad de conos. El resultado de mi auto tortura fue el siguiente algoritmo:


  1. Lanzamos el contenedor Docker en modo interactivo.


    docker run --privileged -it docker:18.09.6 

    Presta atención a la versión del contenedor, un paso hacia la derecha o hacia la izquierda y tu DinD se convertirá en una calabaza. De hecho, todo se rompe con bastante frecuencia con el lanzamiento de una nueva versión.
    Debemos entrar inmediatamente en el caparazón.


  2. Intentando averiguar qué contenedores se están ejecutando (Respuesta: ninguno), pero ejecutemos el comando de todos modos:


     docker ps 

    Te sorprenderás un poco, pero resulta que el demonio Docker ni siquiera se está ejecutando:


     error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 192.168.65.1:53: no such host 

  3. Ejecútelo usted mismo:


     dockerd & 

    Otra sorpresa desagradable:


     failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not found 

  4. Instale los paquetes iptables y bash (es más agradable trabajar en bash que en sh):


     apk add --no-cache iptables bash 

  5. Empezamos bash. Finalmente estamos de vuelta en el caparazón habitual


  6. intenta iniciar Docker nuevamente:


     dockerd & 

    Deberíamos ver una hoja de registro larga que termina:


     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 

  7. Presione Entrar. Estamos de vuelta en la fiesta.



A partir de ahora, podemos intentar lanzar otros contenedores dentro de nuestro contenedor Docker, pero ¿qué sucede si queremos elevar otro contenedor Docker dentro de nuestro contenedor Docker o algo sale mal y el contenedor se "volará"? Comience todo de nuevo.


Propio contenedor DinD y nuevos experimentos



Para no repetir los pasos anteriores una y otra vez, creé mi propio contenedor DinD:


https://github.com/alekslitvinenk/dind


La solución de trabajo de DinD me dio la oportunidad de ejecutar Docker dentro de Docker de forma recursiva y realizar experimentos más audaces.
Un experimento (exitoso) con la ejecución de MySQL y Nodejs, voy a describirlo ahora.
Los más impacientes pueden ver cómo fue aquí



Entonces, comencemos:


  1. Inicie DinD de forma interactiva. En esta versión de DinD, necesitamos mapear manualmente todos los puertos que nuestros contenedores secundarios pueden usar (ya estoy trabajando en esto)


     docker run --privileged -it \ -p 80:8080 \ -p 3306:3306 \ alekslitvinenk/dind 

    Nos encontramos en una fiesta, desde donde podemos comenzar inmediatamente a lanzar contenedores subsidiarios.


  2. Iniciamos MySQL:


     docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql 

  3. Nos conectamos a la base de datos de la misma manera que nos conectaríamos a ella localmente. Asegúrate de que todo funcione.


  4. Lanzamos el segundo contenedor:


     docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server 

    Tenga en cuenta que la asignación de puertos aquí será exactamente 8080: 8080 , ya que ya hemos asignado el puerto 80 desde el host al contenedor principal en el puerto 8080.


  5. Vamos a localhost en el navegador, estamos convencidos de que el servidor responde "¡Hola Mundo!".



En mi caso, el experimento con los contenedores acoplados adjuntos fue bastante positivo, y continuaré desarrollando el proyecto y usándolo para la puesta en escena. Me parece que esta es una solución mucho más ligera que los mismos Kubernetes y Jenkins X. Pero esta es mi opinión subjetiva.


Creo que esto es todo para el artículo de hoy. En el próximo artículo, describiré con más detalle los experimentos con el lanzamiento recursivo de Docker en Docker y el montaje de directorios en contenedores anidados.


PD: si este proyecto le resulta útil, dele un asterisco en GitHub, bifurque y dígaselo a sus amigos.


Edición1 Errores corregidos , enfocados en 2 videos

Source: https://habr.com/ru/post/477464/


All Articles