Confusão com Jenkins Docker Plugin e Jenkins Docker Slaves

Portanto, estou agradavelmente surpreso em alguns aspectos ao ver o plug-in Jenkins Docker "empurrando" imagens Docker para o meu Docker host metal, mas também é confuso porque minhas compilações estão ocorrendo em contêineres Docker Slave que estão sendo executados no Docker host metal. Mesmo meu Mestre Jenkins corre em um contêiner Docker, não diretamente no metal...

Seguindo este popular Jenkins mestre / escravo guia Cheguei ao ponto em que eu tinha compilações Jenkins trabalhando em contentores Docker Efêmeros.

Isso significa que quando eu faço Jenkins uma compilação de algum componente/serviço de software de código-fonte Meu, a compilação é iniciada em um escravo Jenkins que passa a ser um contêiner Docker girado pelo plug-in Jenkins Docker.

O espaço de trabalho Jenkins está neste contêiner escravo, O Mestre Jenkins com o plug-in Docker instalado, descartará esse contêiner escravo assim que a compilação for concluída. Veja um diagrama que fiz para ajudar a explicar:

enter image description here

Alguns pontos de acompanhamento importantes depois de ter digerido este diagrama:

  • O Jenkins Master e o Jenkins Slave estão rodando no mesmo Docker Host Metal neste momento, já que estou apenas nos estágios iniciais de fazer esse sistema funcionar
  • Estou usando o plug-in Docker e o plug-in SSH Slaves para realizar esta configuração

Portanto, dentro deste Docker Slave, meu artefato de compilação de componente/serviço de software é criado, pode ser, por exemplo, um .dll ou um .guerra. Acontece que é o caso, porém, que meu artefato de compilação será uma imagem do Docker. Para ser claro, estou construindo uma imagem Docker dentro de um contêiner Docker em execução (o escravo Jenkins).

Minha confusão começa com minha expectativa de que eu deveria ter que executar explicitamente um cmd para enviar meu artefato de construção de imagem Docker de componente de software para um registro Docker. Caso contrário, quando o trabalho de construção do Jenkins estiver concluído, o plug-in do Docker desligará o escravo do contêiner do Docker, descartará (rm) o contêiner escravo e, em seguida, perderei o artefato de construção dentro desse contêiner escravo.

O que realmente acontece, e por que estou agradavelmente surpreso, pelo menos no curto prazo enquanto estou colocando devops em funcionamento, é que a imagem do Docker do artefato de construção aparece no metal do host do Docker, docker image ls.

Estou surpreso que o plugin Docker iria para este nível de suposição / ajuda... Eu sei que o plugin Docker permite que você configure um registro Docker e que você pode adicionar uma etapa de compilação para construir / publicar em uma nuvem Docker que presumo que a nuvem seja tratada como um registro para imagens e talvez um lugar para também executar essas imagens também:

enter image description here

O que é particularmente interessante é que não estou usando o plug-in Docker para nenhuma etapa de compilação, apenas Uso o plug-in Docker para configurar um contêiner escravo para o item build Jenkins:

enter image description here

A única etapa de compilação que tenho é que executo um Script de Shell, sim, esse script acaba criando uma imagem do Docker, mas o plug-in do Docker não saberia disso:

enter image description here

O plug-in Docker gira os contêineres Docker Slave, configuro o plug-in Docker e digo a ele um Host Docker (meu metal na minha situação) uma nuvem é o que o plug-in Docker chama de Host Docker e também imagens Docker slave para usar nesse Host/nuvem Docker:

enter image description hereEu só tenho mal-entendidos sobre o quão isolado um espaço de trabalho de construção Jenkins acontece quando dentro de um contêiner escravo Docker?

O plug-in Docker está apenas padronizando o uso da única nuvem Docker (meu Docker host metal) que tenho configurado para todos os comandos docker que executo dentro de um contêiner Jenkins Docker slave? (um contêiner escravo, a propósito, que tem Docker-CE instalado nele)

As Jenkins Master Dockerfile:

#reference#https://engineering.riotgames.com/news/putting-jenkins-docker-containerFROM jenkins:2.60.1MAINTAINER Brian OgdenUSER root#TimezoneENV TZ=America/Los_AngelesRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone# Prep Jenkins DirectoriesRUN mkdir /var/log/jenkinsRUN mkdir /var/cache/jenkinsRUN chown -R jenkins:jenkins /var/log/jenkinsRUN chown -R jenkins:jenkins /var/cache/jenkins# Copy in local config filesfilesCOPY plugins.sh /usr/local/bin/plugins.shRUN chmod +x /usr/local/bin/plugins.sh# Install default plugins# Set list of plugins to download / update in plugins.txt like this# pluginID:version# credentials:1.18# maven-plugin:2.7.1# ...# NOTE : Just set pluginID to download latest version of plugin.# NOTE : All plugins need to be listed as there is no transitive dependency resolution.COPY plugins.txt /tmp/plugins.txtRUN /usr/local/bin/plugins.sh /tmp/plugins.txtUSER jenkins#give Jenkins a nice 8 GB memory pool and room to handle garbage collection#ENV JAVA_OPTS="-Xmx8192m"#give Jenkins a nice base pool of handlers and a cap#ENV JENKINS_OPTS="--handlerCountStartup=100 --handlerCountMax=300"ENV JENKINS_OPTS="--logfile=/var/log/jenkins/jenkins.log --webroot=/var/cache/jenkins/war"

Eu uso o volume docker-compose e Docker com meu Mestre Jenkins, meu docker-compose.yml:

version: '2'services:  data:    build: data    image: tsl.devops.jenkins.data.image    container_name: tsl.devops.jenkins.data.container  master:    build: master    image: tsl.devops.jenkins.master.image    container_name: tsl.devops.jenkins.master.container    volumes_from:      - data    ports:      - "50000:50000"    #network_mode: "host"  nginx:    build: nginx    image: tsl.devops.jenkins.nginx.image    container_name: tsl.devops.jenkins.nginx.container    ports:      - "80:80"    links:      - master:jenkins-master  slavebasic:    build:      context: ./slaves      dockerfile: basic/Dockerfile    image: tsl.devops.jenkins.slave.basic.image    container_name: tsl.devops.jenkins.slave.basic.container  slavedotnetcore:    build:      context: ./slaves      dockerfile: dotnetcore/Dockerfile    image: tsl.devops.jenkins.slave.dotnetcore.image    container_name: tsl.devops.jenkins.slave.dotnetcore.container

As Jenkins Master volume/ drive Dockerfile:

#reference#https://engineering.riotgames.com/news/docker-jenkins-data-persistsFROM centos:7MAINTAINER Brian Ogden#create the Jenkins user in this containerRUN useradd -d "/var/jenkins_home" -u 1000 -m -s /bin/bash jenkins#NOTE: we set the UID here to the same one the Cloudbees Jenkins image uses #so we can match UIDs across containers, which is essential if you want #to preserve file permissions between the containers. We also use the same home directory and bash settings.#Jenkins log directoryRUN mkdir -p /var/log/jenkinsRUN chown -R jenkins:jenkins /var/log/jenkins#Docker volume magicVOLUME ["/var/log/jenkins", "/var/jenkins_home"]USER jenkins#just a little output reminder of the container's purposeCMD ["echo", "Data container for Jenkins"]

As Escravo Dockerfile:

FROM centos:7MAINTAINER Brian Ogden#the USER will be root by default just explicitly #expressing it for better documentationUSER root# Install EssentialsRUN yum update -y && \         yum clean all############################################## Jenkins Slave setup#############################################RUN yum install -y \    git \    wget \    openssh-server \    java-1.8.0-openjdk \    sudo \    make && \    yum clean all# gen dummy keys, centos doesn't autogen them like ubuntu doesRUN /usr/bin/ssh-keygen -A# Set SSH Configuration to allow remote logins without /proc write accessRUN sed -ri 's/^session\s+required\s+pam_loginuid.so$/session optional pam_loginuid.so/' /etc/pam.d/sshd# Create Jenkins UserRUN useradd jenkins -m -s /bin/bash# Add public key for Jenkins loginRUN mkdir /home/jenkins/.sshCOPY /files/id_rsa.pub /home/jenkins/.ssh/authorized_keys#setup permissions for the new folders and filesRUN chown -R jenkins /home/jenkinsRUN chgrp -R jenkins /home/jenkinsRUN chmod 600 /home/jenkins/.ssh/authorized_keysRUN chmod 700 /home/jenkins/.ssh# Add the jenkins user to sudoersRUN echo "jenkins  ALL=(ALL)  ALL" >> etc/sudoers########################################################################################### Docker and Docker Compose Install##############################################install required packagesRUN yum install -y \    yum-utils \    device-mapper-persistent-data \    lvm2 \    curl && \    yum clean all#add Docker CE stable repositoryRUN yum-config-manager \    --add-repo \    https://download.docker.com/linux/centos/docker-ce.repo#Update the yum package index.RUN yum makecache fast#install Docker CERUN yum install -y docker-ce-17.06.0.ce-1.el7.centos#install Docker Compose 1.14.0#download Docker Compose binary from github repoRUN curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose#Apply executable permissions to the binaryRUN chmod +x /usr/local/bin/docker-compose########################################################################################### .NET Core SDK#############################################RUN yum install -y \    libunwind \    libicuRUN curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?linkid=848821RUN mkdir -p /opt/dotnet && tar zxf dotnet.tar.gz -C /opt/dotnetRUN ln -s /opt/dotnet/dotnet /usr/local/bin#add Trade Service Nuget ServerRUN mkdir -p /home/jenkins/.nuget/NuGetCOPY /files/NuGet.Config /home/jenkins/.nuget/NuGet/NuGet.ConfigRUN chown -R jenkins /home/jenkins/.nugetRUN chgrp -R jenkins /home/jenkins/.nugetRUN chmod 600 /home/jenkins/.nuget/NuGet/NuGet.ConfigRUN chmod 700 /home/jenkins/.nuget/NuGet#speed up dotnet core buildsENV NUGET_XMLDOC_MODE skipENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE true############################################## Expose SSH port and run SSHDEXPOSE 22#Technically, the Docker Plugin enforces this call when it starts containers by overriding the entry command. #I place this here because I want this build slave to run locally as it would if it was started in the build farm.CMD ["/usr/sbin/sshd","-D"]

Exemplo software / componente Dockerfile que criará um artefato de construção de imagem Docker dentro de um contêiner Docker escravo Jenkins:

FROM centos:7MAINTAINER Brian Ogden#TimezoneENV TZ=America/Los_AngelesRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezoneRUN yum update -y && \         yum clean all############################################## .NET Core SDK#############################################RUN yum install -y \    libunwind \    libicuRUN curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?linkid=848821RUN mkdir -p /opt/dotnet && tar zxf dotnet.tar.gz -C /opt/dotnetRUN ln -s /opt/dotnet/dotnet /usr/local/bin#speed up dotnet core buildsENV NUGET_XMLDOC_MODE skipENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE true########################################################################################### .NET Sevrice setup#############################################ARG ASPNETCORE_ENVIRONMENT# Copy our code from the "/src/MyWebApi/bin/Debug/netcoreapp1.1/publish" folder to the "/app" folder in our containerWORKDIR /appCOPY ./src/TSL.Security.Service/bin/Debug/netcoreapp1.1/publish .# Expose port 5000 for the Web API trafficENV ASPNETCORE_URLS http://+:5000ENV ASPNETCORE_ENVIRONMENT $ASPNETCORE_ENVIRONMENT EXPOSE 5000# Run the dotnet application against a DLL from within the container# Don't forget to publish your application or this won't workENTRYPOINT ["dotnet", "TSL.Security.Service.dll"]#############################################

De acordo com a configuração do plugin Docker, você está usando 172.17.0.1 como o anfitrião Docker. Do contêiner escravo ou mestre, este será o daemon Docker em execução no host (não há Docker no Docker acontecendo aqui). Quando seu escravo Jenkins constrói uma imagem (independentemente se o escravo estiver sendo executado como um contêiner ou no host), ele está usando o Docker no host e é por isso que sua imagem aparece no host.

Vale a pena notar que os dados provavelmente vão primeiro para o volume do Docker que está sendo usado pelo escravo (de acordo com o Jenkins Dockefile em https://github.com/jenkinsci/docker/blob/9f29488b77c2005bbbc5c936d47e697689f8ef6e/Dockerfile o padrão é /var/jenkins_home). No seu caso, este é apenas um volume do data serviço (no entanto, no formato Compose v2, você pode apenas definir um volume nomeado, você não precisa criar um contêiner de dados). A partir daqui, seu código e Dockerfile seja enviado para o contexto de construção do Docker no host por meio da API em tcp://172.17.0.1:4243.

Você pode confirmar o layout do host? O mestre e escravo Jenkins está em diferentes hosts físicos? Além disso, quais plug-ins do Docker você está usando? Noto que há pelo menos dois para Jenkins (plug-in Docker e plug-in Docker Slaves, Não tenho certeza se você está usando um ou ambos ou outros).

Oi @ AndyShinn, atualizei minha pergunta para responder às suas perguntas", - o Jenkins Master e o Jenkins Slave estão rodando no mesmo Docker Host Metal neste momento, pois estou apenas nos estágios iniciais de execução deste sistema

  • Estou usando o plug-in Docker e o plug-in SSH Slaves para realizar essa configuração"

Tenho uma explicação que posso dar. Mas estou confuso em mais algumas partes que talvez você possa esclarecer. 1) como o plug-in Docker slaves sabe para lançar Jenkins como a imagem slave Docker? Não está claro para mim como o escravo Jenkins realmente lança a imagem do Dockerfile que você fornece. 2) você pode confirmar o comando ‘docker run’ que usou para iniciar o mestre? Estou me perguntando se ele passa no soquete de controle do Docker, caso em que qualquer compilação no contêiner usaria apenas o Docker do host (portanto, por que você está vendo a imagem sendo construída no host). Vou descrever isso como uma resposta.

@ AndyShinn ok, atualizei minha pergunta com as informações solicitadas. Eu adicionei meu Dockerfile para meu Mestre Jenkins, que tem um volume Docker, então adicionei meu Dockerfile para o volume de dados mestre Jenkins também. Eu também expliquei, incluindo a captura de tela de configuração do Jenkins, como você configura o “plug-in Docker”, não o plug-in Docker slaves como você o chamou, para usar uma imagem Docker definida como um escravo, meu Dockerfile para meu escravo foi incluído em minha pergunta original