Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

[Jenkins e Docker] docker não encontrado no passo de build

Olá, estou realizando o curso de Jenkins e Docker: Pipeline de entrega continua

Diferente do instrutor, estou utilizando o Jenkins em um container do docker. Fiz a instalação do plugin, configurei a cloud apontando para o docker, e deu tudo certo. Ao testar a conexão com o daemon na configuração da Cloud recebi o seguinte retorno: Version = 27.1.1, API Version = 1.46

Porém, ao executar o pipeline para fazer o lint do Dockerfile é gerado o erro no console:

+ docker run --rm -i hadolint/hadolint
/tmp/jenkins8551744553953196734.sh: 3: docker: not found
Build step 'Execute shell' marked build as failure
Finished: FAILURE

Meu docker compose está criando o Jenkins com essas configurações:

services: 
  jenkins:
    container_name: jenkins
    image: jenkins/jenkins
    ports:
      - 8081:8080
    networks:
      - my_network
    volumes:
      - jenkins-docker-certs:/certs/client
      - jenkins-home:/var/jenkins_home

Tentei realizando a instalação do docker no mesmo host do Jenkins, mas é apresentado o erro de socket.

Minha dúvida não se resume apenas ao porquê não está funcionando. Mas gostaria de entender se o responsável por realizar a gestão do docker no host do Jenkins é o plugin junto com a configuração da cloud, ou se realmente é necessário a instalação do docker juntamente com o Jenkins. E assim, realizar a configuração do socket. Pois seriam dois clients apontando para o mesmo daemon.

4 respostas

Olá, Márcia. Tudo bem?

Quando você está executando o Jenkins dentro de um container Docker, ele não tem acesso direto ao Docker do host, a menos que você configure isso explicitamente. O erro que você está enfrentando ("docker: not found") ocorre porque o comando docker não está disponível dentro do container Jenkins.

Para resolver isso, você tem algumas opções:

  1. Montar o socket do Docker do host no container do Jenkins: Isso permite que o Jenkins use o Docker do host. Você pode modificar seu docker-compose.yml para incluir o socket do Docker. Aqui está um exemplo de como fazer isso:

    services: 
      jenkins:
        container_name: jenkins
        image: jenkins/jenkins
        ports:
          - 8081:8080
        networks:
          - my_network
        volumes:
          - jenkins-docker-certs:/certs/client
          - jenkins-home:/var/jenkins_home
          - /var/run/docker.sock:/var/run/docker.sock
    

    Ao adicionar a linha - /var/run/docker.sock:/var/run/docker.sock, você está permitindo que o Jenkins dentro do container se comunique com o Docker do host.

  2. Instalar o Docker dentro do container Jenkins: Outra abordagem é instalar o Docker dentro do próprio container Jenkins. Isso pode ser feito criando um Dockerfile personalizado que instala o Docker CLI no container Jenkins. No entanto, isso é menos comum e pode ser mais complicado de gerenciar.

  3. Utilizar agentes Docker: Configure o Jenkins para usar agentes Docker que podem ser criados e destruídos conforme necessário. Isso é feito através do plugin Docker do Jenkins, que você mencionou já ter configurado. Essa abordagem é mais alinhada com a filosofia de containers, mas requer uma configuração inicial mais complexa.

A primeira opção é a mais comum e simples para começar. No entanto, é importante estar ciente das implicações de segurança ao expor o socket Docker para o container, pois isso concede ao Jenkins acesso total ao Docker do host.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.Bons Estudos!

Olá, obrigado pela resposta, e pelo tempo dispensado para analisar minha questão.

Sobre a solução 1, eu já havia tentado realizar essa configuração, porém estou executando o docker desktop via windows e não tive sucesso ao realizar a configuração da permissão do usuário administrador/root no container docker para utilizar o socket do host.

Uma questão que ainda não está clara para mim, mesmo utilizando a opção 1 ou 3, é necessário a instalação do cliente do docker no container do Jenkins?

Pois o plugin (Docker plugin Versão1.7.0) já solicita uma conexão com um docker externo, onde configurei o docker desktop para expor o serviço tcp://localhost:2375, e configurei no Jenkins utilizando o tcp://host.docker.internal:2375. Recebi um sucesso após essa configuração.

Os passos que estou seguindo são referentes a esta aula: https://cursos.alura.com.br/course/pipeline-ci-jenkins-docker/task/57286

Olá, Márcia! Tudo bem?

Vou trazer algumas explicações para ver se consigo esclarecer suas dúvidas.

Pergunta:

"Uma questão que ainda não está clara para mim: mesmo utilizando a opção 1 ou 3, é necessário instalar o cliente do Docker no container do Jenkins?"

Resposta:

Se você subir o Jenkins em um contêiner e instalar o Docker dentro do próprio container do Jenkins, não é necessário instalar o plugin do Docker. Nesse caso, você utilizaria uma imagem base do Jenkins personalizada. A configuração do arquivo docker-compose.yml ficaria assim:

services: 
  jenkins:
    container_name: jenkins
    build:
      context: .
    ports:
      - 8081:8080
    networks:
      - my_network
    volumes:
      - jenkins-docker-certs:/certs/client
      - jenkins-home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock

Perceba que, em vez de passar a imagem base do Jenkins diretamente, foi definido um contexto para que o docker-compose utilize uma personalização com um arquivo Dockerfile, que ficaria assim:

FROM jenkins/jenkins
USER root
RUN apt-get update -qq \
    && apt-get install -qqy apt-transport-https ca-certificates vim curl gnupg2 software-properties-common
RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
RUN add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/debian \
    $(lsb_release -cs) \
    stable"
RUN apt-get update -qq \
    && apt-get -y install docker-ce
RUN usermod -aG docker jenkins

WORKDIR /home

Com isso, o Docker já estará configurado dentro do container Jenkins, dispensando o uso do plugin.

Pergunta:

"O plugin (Docker plugin Versão 1.7.0) já solicita uma conexão com um Docker externo. Configurei o Docker Desktop para expor o serviço em tcp://localhost:2375 e configurei no Jenkins utilizando tcp://host.docker.internal:2375. Recebi um sucesso após essa configuração, mas gostaria de entender melhor."

Resposta:

Mesmo que sua configuração tenha funcionado, gostaria de trazer uma explicação para você a diferença entre tcp://localhost:2375 e tcp://host.docker.internal:2375. Essa diferença está relacionada à forma como o Docker Desktop e o Windows lidam com redes e acessos entre containers e o host.

Por que tcp://localhost:2375 não funcionou?

  1. Contexto de rede dentro do container:

    • Quando você usa localhost dentro de um container, ele se refere ao próprio container, e não ao host.
    • Como o serviço Docker não está rodando no container Jenkins, tcp://localhost:2375 não funcionará.
  2. Isolamento de rede:

    • Containers são isolados por padrão, então é necessário apontar explicitamente para o host do Docker.

Por que tcp://host.docker.internal:2375 funcionou?

  1. Acesso direto ao host do Docker:

    • host.docker.internal é um alias DNS fornecido pelo Docker Desktop no Windows e macOS. Ele permite que containers acessem serviços rodando no host.
  2. Solução específica do Docker Desktop:

    • Essa funcionalidade foi implementada para facilitar o desenvolvimento em Windows e macOS, permitindo comunicação direta entre containers e o host.

Espero ter ajudado e bons estudos!

solução!

Olá, agradeço a resposta.

Ok, entendi que caso a configuração do plugin seja concluída com sucesso, não é necessário a instalação do cliente docker no container jenkins. Porém, mesmo com a configuração do plugin, o erro reportado no pipeline é de que o 'docker' não é um comando conhecido.

De qualquer forma segui pela opção de instalar o docker no host do jenkins direto conforme orientado pelo Paulo Alves, porém o dockerfile informado não funciona. Ao analisar o erro identifiquei alguns problemas como

  • o lsb que não existe na imagem default do jenkins (jenkins/jenkins);
  • a adição de um novo repositório não está reconhecendo o caminho.

Sendo assim, alterei a construção da imagem para:

FROM jenkins/jenkins
USER root

RUN apt-get update && \ 
    apt-get install ca-certificates curl && \ 
    install -m 0755 -d /etc/apt/keyrings && \ 
    curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc && \ 
    chmod a+r /etc/apt/keyrings/docker.asc

RUN echo \
    "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
    $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
    tee /etc/apt/sources.list.d/docker.list > /dev/null

RUN apt-get update -qq \
    && apt-get -y install docker-ce
RUN usermod -aG docker jenkins

WORKDIR /home

Desta forma funcionou para mim.

Att,