Como lancei o Docker dentro do Docker e o que aconteceu

Olá pessoal! No artigo anterior , prometi falar sobre o lançamento do Docker no Docker e os aspectos práticos da aplicação desta lição. É hora de cumprir nossa promessa. Um devedor experiente, talvez, argumentaria que aqueles que precisam do Docker dentro do Docker apenas jogam o soquete demônio do Docker do host dentro do contêiner e isso é suficiente em 99% dos casos. Mas não se apresse em jogar biscoitos para mim, porque falaremos sobre o lançamento real do Docker dentro do Docker. Esta solução tem muitos campos de aplicação possíveis e este artigo é sobre um deles; portanto, sente-se e endireite os braços à sua frente.


imagem

Iniciar


Tudo começou em uma noite chuvosa de setembro, quando eu estava limpando um carro alugado pela Digital Ocean por US $ 5, o que ficou estagnado porque o Docker preencheu todos os 24 gigabytes de espaço disponível em disco com suas imagens e contêineres. A ironia era que todas essas imagens e contêineres eram transitórios e precisavam apenas testar o desempenho do meu aplicativo toda vez que uma nova versão de uma biblioteca ou estrutura era lançada. Tentei escrever scripts de shell e configurar a programação das coroas para limpeza de lixo, mas isso não salvou: toda vez que, inevitavelmente, o espaço em disco do meu servidor acabava sendo consumido e o servidor travava (na melhor das hipóteses). Em algum momento, deparei com um artigo sobre como executar o Jenkins em um contêiner e como ele pode criar e excluir pipelines de montagem através do soquete do daemon do docker lançado nele. Gostei da ideia, mas decidi seguir em frente e tentar experimentar o lançamento direto do Docker dentro do Docker. Pareceu-me então uma decisão completamente lógica extrair imagens do docker e criar contêineres de todos os aplicativos necessários para testar dentro de outro contêiner (vamos chamá-lo de contêiner intermediário). A ideia era executar um contêiner intermediário com o sinalizador -rm, que exclui automaticamente todo o contêiner com todo o seu conteúdo quando ele para. Eu vasculhei a imagem do docker do próprio Docker ( https://hub.docker.com/_/docker ), mas acabou sendo muito volumoso e não consegui fazê-lo funcionar conforme necessário e queria seguir todo o caminho.


Prática. Solavancos


Decidi fazer o contêiner funcionar conforme necessário e continuei minhas experiências, o que resultou em uma infinidade de cones. O resultado da minha auto-tortura foi o seguinte algoritmo:


  1. Iniciamos o contêiner do Docker em um modo interativo.


    docker run --privileged -it docker:18.09.6 

    Preste atenção à versão do recipiente, um passo para a direita ou para a esquerda e seu DinD se transforma em abóbora. De fato, tudo se quebra com bastante frequência com o lançamento de uma nova versão.
    Devemos entrar imediatamente na concha.


  2. Tentando descobrir quais contêineres estão sendo executados (Resposta: nenhuma), mas vamos executar o comando de qualquer maneira:


     docker ps 

    Você ficará um pouco surpreso, mas acontece que o daemon do Docker nem está em execução:


     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. Vamos executá-lo você mesmo:


     dockerd & 

    Outra surpresa desagradável:


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

  4. Instale os pacotes iptables e bash (é mais agradável trabalhar no bash do que no sh):


     apk add --no-cache iptables bash 

  5. Começamos o bash. Finalmente, estamos de volta ao habitual


  6. tente iniciar o docker novamente:


     dockerd & 

    Deveríamos ver uma longa folha de registro terminando:


     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. Pressione Enter. Estamos de volta à festa.



A partir de agora, podemos tentar lançar outros contêineres dentro do contêiner do Docker, mas e se quisermos levantar outro contêiner do Docker dentro do contêiner do Docker ou se algo der errado e o contêiner "voar para fora"? Comece tudo de novo.


Contêiner DinD próprio e novas experiências



Para não repetir as etapas acima, criei meu próprio contêiner DinD:


https://github.com/alekslitvinenk/dind


A solução de trabalho DinD me deu a oportunidade de executar o Docker dentro do Docker recursivamente e realizar experiências mais ousadas.
Um desses experimentos (bem-sucedidos) com a execução de MySQL e Nodejs, vou descrever agora.
O mais impaciente pode ver como foi aqui



Então, vamos começar:


  1. Inicie o DinD interativamente. Nesta versão do DinD, precisamos mapear manualmente todas as portas que nossos contêineres filhos podem usar (já estou trabalhando nisso)


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

    Nós nos encontramos em uma festa, de onde podemos começar imediatamente a lançar contêineres subsidiários.


  2. Iniciamos o MySQL:


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

  3. Nós nos conectamos ao banco de dados da mesma maneira que nos conectamos localmente. Verifique se tudo funciona.


  4. Lançamos o segundo contêiner:


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

    Observe que o mapeamento da porta aqui será exatamente 8080: 8080 , pois já mapeamos a porta 80 do host para o contêiner pai na porta 8080.


  5. Nós vamos para o host local no navegador, estamos convencidos de que o servidor responde "Olá, mundo!".



No meu caso, o experimento com os contêineres do docker fechados foi bastante positivo, e continuarei desenvolvendo o projeto e usá-lo para preparação. Parece-me que esta é uma solução muito mais leve que a mesma Kubernetes e Jenkins X. Mas esta é a minha opinião subjetiva.


Eu acho que isso é tudo para o artigo de hoje. No próximo artigo, descreverei mais detalhadamente experimentos com o lançamento recursivo do Docker no Docker e montagem de diretórios em contêineres aninhados.


PS Se você acha este projeto útil, dê um asterisco no GitHub, bifurque-se e conte a seus amigos.


Edit1 Bugs corrigidos , focados em 2 vídeos

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


All Articles