Eu imagino que minha história é muito parecida com a de tantas outras pessoas trabalhando com integração contínua (CI).
Você começa a montar a esteira CI usando Jenkins, e em um determinado momento vem o pensamento:
“Por quê não executar o Jenkins em um container docker?”
E, como um raio, um segundo pensamento cai sobre você:
“Qual docker (executável) o Jenkins vai utilizar para os builds?”
A partir daí, é um caminho sem volta de tentativas e de buscar alguma solução entre documentações, blogs e fóruns online.
Independente do percurso, todos temos um mesmo checkpoint: o artigo de Jérôme Petazzoni sobre Docker-in-Docker (dind, para os intimos).
De forma prática, ao falar de dind, estamos nos referindo a um container docker com uma instalação docker que permite executar outros containers…
(…) que podem ser outros containers docker-in-docker que podem executar outros containers docker-in-docker…
No artigo, temos um dos contribuidores da flag --privileged
, essencial para a execução do dind, criticando o uso do dind para determinados cenários - inclusive para o Jenkins.
Nesse mesmo artigo, uma solução é apresentada: montar o docker.sock
da máquina host como forma do container contendo o Jenkins, executar e guardar seu cache no Docker instalado no host.
Longe de dizer qual das duas alternativas é a “correta” neste post, quero discutir alguns dos pontos envolvendo essas abordagens.
TL;DR
A abordagem de montar o docker.sock
no container, de fato, soluciona as potenciais questões de data corruption (pelo compartilhamento do /var/lib/docker
) e de incompatibilidade entre filesystems relacionadas ao docker-in-docker.
Por outro lado, ao expor o docker.sock
para o container, este se torna um ponto de vulnerabilidade, em termos de segurança, por dar acesso completo ao usuário (root) do docker da máquina host - tornando possível executar containers com código malicioso. No caso de um usuário não-root, a situação ainda piorará pela necessidade de alteração das permissões do docker.sock
.
Finalmente, o que vai decidir a melhor abordagem são os requisitos de seu projeto e a análise dos potenciais riscos em seu ambiente produtivo.
Para facilitar o teste/implementação das abordagens citadas, disponibilizei os seguintes arquivos docker-compose
com as instruções necessárias para executar sua aplicação Jenkins com dind ou com a montagem do socket.
Jenkins associado a um container docker-in-docker
Container Jenkins com o docker.sock montado
Referências
[1] Artigo original de Jérôme Petazzoni
[2] Artigo sobre a vulnerabilidade de montar o docker.sock
[3] Discussão sobre a vulnerabilidade de montar o docker.sock
[4] Documentação oficial da imagem docker:dind
[5] Instruções para execução do docker-in-docker associado ao Jenkins
Agradecimentos ao @renancmonteiro_ pelas discussões sobre o tema!
Esta é uma modalidade de post “rápido”, onde apresento as principais conclusões sobre algum tema e compartilho códigos que possam ajudar nos problemas envolvidos. Uma discussão detalhada será publicada e linkada posteriormente.