Confusão com o Jenkins Docker Plugin e Jenkins Docker Slaves

4

Então estou agradavelmente surpreso em alguns aspectos por ver o plugin do Jenkins Docker "empurrando" imagens do Docker para o meu host do Docker, mas é confuso também porque minhas construções estão ocorrendo no Docker Slave Containers em execução no host do Docker . Mesmo meu mestre Jenkins é executado em um contêiner Docker, não diretamente no metal ...

Seguindo este popular Guia mestre / escravo de Jenkins , cheguei ao ponto em que tive Jenkins trabalhando em contêineres 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, a compilação é iniciada em um escravo Jenkins que é um Docker Container criado pelo Jenkins Docker Plugin.

O espaço de trabalho do Jenkins está neste contêiner de escravos, o mestre Jenkins com o Docker Plugin instalado, descartará esse contêiner de escravos assim que a construção estiver concluída. Veja um diagrama que fiz para ajudar a explicar:

Algunspontosdeacompanhamentoimportantesdepoisdeterdigeridoestediagrama:

  • OJenkinsMastereoJenkinsSlaveestãorodandonomesmoDockerHostMetalnestemomento,jáqueestouapenasnosestágiosiniciaisdeexecuçãodestesistema
  • Estouusandooplug-inDockereoplug-inSSHSlavespararealizaressaconfiguração

Assim,dentrodesteDockerSlave,meuartefatodecomponentedeserviço/construçãodeserviçoécriado,porexemplo,umarquivo.dllou.war.Acontece,noentanto,queomeuartefatodeconstruçãoseráumaimagemdoDocker.Paradeixarclaro,estouconstruindoumaimagemdoDockerdentrodeumcontêinerdoDockeremexecução(oJenkinsSlave).

MinhaconfusãocomeçacomaminhaexpectativadequedevoexecutarexplicitamenteumcmdparaenviarmeuartefatodecompilaçãodeimagemdoDockerdocomponentedesoftwareparaumregistrodoDocker.Casocontrário,quandootrabalhodeconstruçãodoJenkinsestiverconcluído,oplug-indoDockerdesligaráoescravodocontêinerdoDocker,descartará(rm)ocontêinerdoescravoeentãoperderáoartefatodeconstruçãodentrodessecontêinersecundário.

Oquerealmenteacontece,eporqueestouagradavelmentesurpreso,pelomenosacurtoprazoenquantoeuestouusandoodevops,équeaimagemdoDockerdoartefatodecompilaçãoaparecenometaldoDocker,dockerimagels.

Estousurpresoqueoplug-indoDockerváparaesseníveldesuposição/ajuda...Euseiqueoplug-indoDockerpermiteconfigurarumregistrodoDockerequevocêpodeadicionarumaetapadecompilaçãoparacriar/publicaremumDockerCloudqueeuassumoqueanuvemétratadacomoumregistroparaimagensetalvezumlugarparatambémexecutaressasimagenstambém:

OqueéparticularmenteinteressanteéqueeunãoestouusandooDockerPluginparanenhumaetapadecompilação,apenasusooDockerPluginparaconfigurarumSlaveContainerparacompilaroJenkinsItem:

AúnicaetapadecriaçãoquetenhoéqueeuexecutoumscriptShell,sim,estescriptacabaporconstruirumaimagemdoDocker,masoDockerPluginnãosaberiadisso:

ODockerPluginfazoDockerSlaveContainers,euconfigurooDockerPluginedigoaeleumDockerHost(meumetalnaminhasituação)éumanuvemqueoDockerPluginchamadeDockerHostetambémimagensescravasdoDockerparausaresseDockerHost/Cloud:

Eusótenhomal-entendidossobrecomoumlocaldetrabalhodeconstruçãoJenkinsficaisoladoquandodentrodeumcontêinerdeescravodoDocker?

OPlug-indoDockeréopadrãoparausarapenasoDockerCloud(meumetalhostdoDocker)?EuconfigureitodososcomandosdodockerqueeuexecutedentrodeumcontêinerdeescravodoJenkinsDocker?(umcontêinerdeescravospelamaneiraqueoDocker-CEestáinstalado)

MeumestredoJenkinsDockerfile:

#reference#https://engineering.riotgames.com/news/putting-jenkins-docker-containerFROMjenkins:2.60.1MAINTAINERBrianOgdenUSERroot#TimezoneENVTZ=America/Los_AngelesRUNln-snf/usr/share/zoneinfo/$TZ/etc/localtime&&echo$TZ>/etc/timezone#PrepJenkinsDirectoriesRUNmkdir/var/log/jenkinsRUNmkdir/var/cache/jenkinsRUNchown-Rjenkins:jenkins/var/log/jenkinsRUNchown-Rjenkins:jenkins/var/cache/jenkins#CopyinlocalconfigfilesfilesCOPYplugins.sh/usr/local/bin/plugins.shRUNchmod+x/usr/local/bin/plugins.sh#Installdefaultplugins#Setlistofpluginstodownload/updateinplugins.txtlikethis#pluginID:version#credentials:1.18#maven-plugin:2.7.1#...#NOTE:JustsetpluginIDtodownloadlatestversionofplugin.#NOTE:Allpluginsneedtobelistedasthereisnotransitivedependencyresolution.COPYplugins.txt/tmp/plugins.txtRUN/usr/local/bin/plugins.sh/tmp/plugins.txtUSERjenkins#giveJenkinsanice8GBmemorypoolandroomtohandlegarbagecollection#ENVJAVA_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 Jenkins Master, 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

Meu volume principal do Jenkins / drive Dockerfile:

#reference
#https://engineering.riotgames.com/news/docker-jenkins-data-persists
FROM centos:7
MAINTAINER Brian Ogden

#create the Jenkins user in this container
RUN 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 directory
RUN mkdir -p /var/log/jenkins
RUN chown -R jenkins:jenkins /var/log/jenkins

#Docker volume magic
VOLUME ["/var/log/jenkins", "/var/jenkins_home"]
USER jenkins

#just a little output reminder of the container's purpose
CMD ["echo", "Data container for Jenkins"]

Meu Slave Dockerfile:

FROM centos:7
MAINTAINER Brian Ogden

#the USER will be root by default just explicitly 
#expressing it for better documentation
USER root

# Install Essentials
RUN 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 does
RUN /usr/bin/ssh-keygen -A

# Set SSH Configuration to allow remote logins without /proc write access
RUN sed -ri 's/^session\s+required\s+pam_loginuid.so$/session optional pam_loginuid.so/' /etc/pam.d/sshd

# Create Jenkins User
RUN useradd jenkins -m -s /bin/bash

# Add public key for Jenkins login
RUN mkdir /home/jenkins/.ssh
COPY /files/id_rsa.pub /home/jenkins/.ssh/authorized_keys

#setup permissions for the new folders and files
RUN chown -R jenkins /home/jenkins
RUN chgrp -R jenkins /home/jenkins
RUN chmod 600 /home/jenkins/.ssh/authorized_keys
RUN chmod 700 /home/jenkins/.ssh

# Add the jenkins user to sudoers
RUN echo "jenkins  ALL=(ALL)  ALL" >> etc/sudoers
#############################################

#############################################
# Docker and Docker Compose Install
#############################################
#install required packages
RUN yum install -y \
    yum-utils \
    device-mapper-persistent-data \
    lvm2 \
    curl && \
    yum clean all

#add Docker CE stable repository
RUN 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 CE
RUN yum install -y docker-ce-17.06.0.ce-1.el7.centos

#install Docker Compose 1.14.0
#download Docker Compose binary from github repo
RUN 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 binary
RUN chmod +x /usr/local/bin/docker-compose
#############################################

#############################################
# .NET Core SDK
#############################################
RUN yum install -y \
    libunwind \
    libicu

RUN curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?linkid=848821
RUN mkdir -p /opt/dotnet && tar zxf dotnet.tar.gz -C /opt/dotnet
RUN ln -s /opt/dotnet/dotnet /usr/local/bin

#add Trade Service Nuget Server
RUN mkdir -p /home/jenkins/.nuget/NuGet
COPY /files/NuGet.Config /home/jenkins/.nuget/NuGet/NuGet.Config

RUN chown -R jenkins /home/jenkins/.nuget
RUN chgrp -R jenkins /home/jenkins/.nuget

RUN chmod 600 /home/jenkins/.nuget/NuGet/NuGet.Config
RUN chmod 700 /home/jenkins/.nuget/NuGet

#speed up dotnet core builds
ENV NUGET_XMLDOC_MODE skip
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE true
#############################################

# Expose SSH port and run SSHD
EXPOSE 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"]

Um exemplo de software / component Dockerfile que criará um artefato de construção de imagem do Docker dentro de um contêiner Jenkins Slave Docker:

FROM centos:7
MAINTAINER Brian Ogden

#Timezone
ENV TZ=America/Los_Angeles
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN yum update -y && \
         yum clean all

#############################################
# .NET Core SDK
#############################################
RUN yum install -y \
    libunwind \
    libicu

RUN curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?linkid=848821
RUN mkdir -p /opt/dotnet && tar zxf dotnet.tar.gz -C /opt/dotnet
RUN ln -s /opt/dotnet/dotnet /usr/local/bin

#speed up dotnet core builds
ENV NUGET_XMLDOC_MODE skip
ENV 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 container
WORKDIR /app
COPY ./src/TSL.Security.Service/bin/Debug/netcoreapp1.1/publish .

# Expose port 5000 for the Web API traffic
ENV ASPNETCORE_URLS http://+:5000
ENV 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 work
ENTRYPOINT ["dotnet", "TSL.Security.Service.dll"]
#############################################
    
por Brian 13.07.2017 / 18:40

1 resposta

2

De acordo com a sua configuração do Docker Plugin, você está usando 172.17.0.1 como o host do Docker. Do escravo ou do contêiner mestre, este será o daemon do Docker em execução no host (não há nenhum Docker no Docker acontecendo aqui). Quando seu escravo Jenkins constrói uma imagem (independente se o escravo está 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 sendo usado pelo escravo (de acordo com o Jenkins Dockefile at link o padrão é /var/jenkins_home ). No seu caso, isso é apenas um volume do serviço data (embora, no formato Compor v2, você possa definir apenas um volume nomeado, não é necessário criar um contêiner de dados). A partir daqui, seu código e Dockerfile são enviados para o contexto de construção do Docker no host por meio da API em tcp://172.17.0.1:4243 .

    
por 13.07.2017 / 23:08