web-dev-qa-db-ja.com

Jenkins DockerプラグインとJenkins Dockerスレーブの混乱

Jenkins DockerプラグインがDockerイメージをDocker Hostメタルに「プッシュ」するのを見て、いくつかの点でうれしい驚きですが、Docker Hostメタルで実行されているDockerスレーブコンテナーでビルドが行われているため、混乱もします。私のJenkinsマスターでさえ、直接金属ではなくDockerコンテナーで実行されます...

この人気のある Jenkinsマスター/スレーブガイド に続いて、 ephemeral Dockerコンテナー でJenkinsビルドを動作させるようになりました。

つまり、私がJenkinsでソースコードソフトウェアコンポーネント/サービスのビルドを実行すると、Jenkins DockerプラグインによってスピンアップされたDockerコンテナであるJenkinsスレーブでビルドが開始されます。

Jenkinsワークスペースはこのスレーブコンテナー内にあり、DockerプラグインがインストールされているJenkinsマスターは、ビルドが完了するとこのスレーブコンテナーを破棄します。説明に役立つように作成した図を参照してください。

enter image description here

この図を要約した後のいくつかの重要なフォローアップポイント:

  • Jenkins MasterとJenkins Slaveは、このシステムを実行する最初の段階なので、現時点では同じDocker Host Metal上で実行されています。
  • 私はDockerプラグインとSSHスレーブプラグインを使用してこのセットアップを実行しています

したがって、このDockerスレーブ内に、ソフトウェアコンポーネント/サービスビルドアーティファクトが作成されます。たとえば、.dllや.warなどです。私のビルドアーティファクトはDockerイメージになりますが、それは偶然です。明確にするために、実行中のDockerコンテナー(Jenkinsスレーブ)内にDockerイメージを構築しています。

私の混乱は、ソフトウェアコンポーネントのDockerイメージビルドアーティファクトをDockerレジストリにプッシュするためにcmdを明示的に実行する必要があるという私の期待から始まります。それ以外の場合、Jenkinsビルドジョブが完了すると、DockerプラグインがDockerコンテナースレーブをシャットダウンし、スレーブコンテナーを破棄(rm)して、そのスレーブコンテナー内のビルドアーティファクトを失います。

実際に何が起こっているのか、そして少なくとも短期間に開発を開始して実行しているときに私が嬉しいことに驚いたのは、ビルドアーティファクトDockerイメージがDocker Hostメタルdocker image lsに表示されることです。

Dockerプラグインがこのレベルの仮定/ヘルプに行くことに驚いています... Dockerプラグインを使用すると、Dockerレジストリを構成でき、Docker Cloudにビルド/パブリッシュするビルドステップを追加できると思います。そのクラウドは、画像のレジストリとして扱われ、おそらくそれらの画像を実行する場所としても扱われます。

enter image description here

特に興味深いのは、ビルド手順にDockerプラグインを使用していないことです。Dockerプラグインを使用して、Jenkinsアイテムをビルドするためのスレーブコンテナーを構成します。

enter image description here

私が持っている唯一のビルドステップは、シェルスクリプトを実行することです。はい、このスクリプトは最終的にDockerイメージをビルドしますが、Dockerプラグインはこれを認識しません。

enter image description here

DockerプラグインはDockerスレーブコンテナーを起動し、Dockerプラグインを構成して、Dockerホスト(私の状況では私の金属)に、DockerプラグインがDockerホストと呼ぶDockerプラグインを呼び出すクラウドと、そのDockerホストで使用するDockerスレーブイメージを伝えます/雲:

enter image description here Dockerスレーブコンテナー内でJenkinsビルドワークスペースがどのように分離されるかについて誤解しているだけですか?

Dockerプラグインは、デフォルトで、唯一のDocker Cloud(私のDockerホストメタル)を使用するように設定されていますか?私がJenkins Dockerスレーブコンテナー内で実行するすべてのDockerコマンド用にセットアップしましたか? (Docker-CEがインストールされているスレーブコンテナー)

ジェンキンスマスターDockerfile:

#reference
#https://engineering.riotgames.com/news/putting-jenkins-docker-container

FROM jenkins:2.60.1
MAINTAINER Brian Ogden

USER root

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

# Prep Jenkins Directories
RUN mkdir /var/log/jenkins
RUN mkdir /var/cache/jenkins
RUN chown -R jenkins:jenkins /var/log/jenkins
RUN chown -R jenkins:jenkins /var/cache/jenkins

# Copy in local config filesfiles
COPY plugins.sh /usr/local/bin/plugins.sh
RUN 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.txt
RUN /usr/local/bin/plugins.sh /tmp/plugins.txt

USER 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"

私のJenkinsマスターであるdocker-compose.ymlでdocker-composeおよびDockerボリュームを使用します。

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

ジェンキンスマスターボリューム/ドライブ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"]

スレーブ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"]

JenkinsスレーブDockerコンテナー内にDockerイメージビルドアーティファクトを作成するsoftware/componentDockerfileの例:

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"]
#############################################
5
Brian

Dockerプラグインの設定によると、Dockerホストとして172.17.0.1を使用しています。スレーブまたはマスターコンテナーから、これはホストで実行されているDockerデーモンになります(DockerでDockerはここでは発生しません)。 Jenkinsスレーブがイメージをビルドするとき(スレーブがコンテナーとして実行されているか、ホスト上で実行されているかは関係ありません)、ホストでDockerを使用しているため、ホストにイメージが表示されます。

データはおそらく最初にスレーブによって使用されているDockerボリュームに送られることに注意してください(Jenkins Dockefileによる https://github.com/jenkinsci/docker/blob/9f29488b77c2005bbbc5c936d47e697689f8ef6e/Dockerfile デフォルトは/var/jenkins_home)です。あなたの場合、これはdataサービスからのボリュームです(ただし、Compose v2形式では、名前付きボリュームを定義するだけでよく、データコンテナーを作成する必要はありません)。ここから、コードとDockerfiletcp://172.17.0.1:4243のAPIを介してホスト上のDockerビルドコンテキストに送信されます。

3
Andy Shinn