建立擁有 C++ 編譯環境及 Jenkins Agent 的 Docker Image - Part 2

前一篇發現預設的 Jenkins Agent 沒有 C++ 編譯環境,所以我們要來解決這個問題。

使用 Docker 安裝 Jenkins Agent 中提到使用的 agent docker image 是 jenkins/jnlp-slave,所以我們先參考一下原本的 Dockerfile 是怎麼寫的 (source)

FROM jenkins/slave:3.26-1
MAINTAINER Oleg Nenashev <[email protected]>
LABEL Description="This is a base image, which allows connecting Jenkins agents via JNLP protocols" Vendor="Jenkins project" Version="3.23"

COPY jenkins-slave /usr/local/bin/jenkins-slave

ENTRYPOINT ["jenkins-slave"]

從內容中可以知道,先複製了 slave 檔案然後啟動 slave,因為複製做一次就好,所以我們只需要啟動 slave。

利用 使用 GitHub 在 DockerHub 自動建置 Docker Image 的方法,建立一個 docker-jenkins-jnlp-slave-cpp github 專案並且建立一個 Dockerfile 檔案,內容就是以 jenkins/jnlp-slave 為基底,加上安裝 C++ 編譯環境,最後記得啟動 slave

FROM jenkins/jnlp-slave:3.26-1

RUN apt update && apt install build-essential -y

ENTRYPOINT ["jenkins-slave"]

接著在 dockerhub 建立 jenkins-jnlp-slave-cpp 自動建置專案,並且手動觸發一次,等著拿建置好的 image 來用,

但是建置結果卻失敗了,來檢查一下 Log,錯誤訊息居然是 List directory /var/lib/apt/lists/partial is missing. - Acquire (13: Permission denied) 權限不足?這沒道理啊,docker 預設是 root,怎麼會有權限問題呢?等等,剛剛是不是提到了預設兩個字。既然如此,那有可能是被改掉了,但是剛剛參考的 Dockerfile 很乾淨,難道是再上一層繼承的 image?

從 Dockerfile 可以看到 jenkins/jnlp-slave 是繼承 jenkins/slave 來的,那來看一下 Dockerfile (source)

FROM openjdk:8-jdk
MAINTAINER Oleg Nenashev <[email protected]>

ARG user=jenkins
ARG group=jenkins
ARG uid=10000
ARG gid=10000

ENV HOME /home/${user}
RUN groupadd -g ${gid} ${group}
RUN useradd -c "Jenkins user" -d $HOME -u ${uid} -g ${gid} -m ${user}
LABEL Description="This is a base image, which provides the Jenkins agent executable (slave.jar)" Vendor="Jenkins project" Version="3.23"

ARG VERSION=3.26
ARG AGENT_WORKDIR=/home/${user}/agent

RUN curl --create-dirs -sSLo /usr/share/jenkins/slave.jar https://repo.jenkins-ci.org/public/org/jenkins-ci/main/remoting/${VERSION}/remoting-${VERSION}.jar \
  && chmod 755 /usr/share/jenkins \
  && chmod 644 /usr/share/jenkins/slave.jar

USER ${user}
ENV AGENT_WORKDIR=${AGENT_WORKDIR}
RUN mkdir /home/${user}/.jenkins && mkdir -p ${AGENT_WORKDIR}

VOLUME /home/${user}/.jenkins
VOLUME ${AGENT_WORKDIR}
WORKDIR /home/${user}

抓到了!其中有一行是 USER ${user},這個指令改變了目前的使用者為 jenkins,造成權限不足以安裝套件。既然如此,那我們就把使用者改回來試試看。

FROM jenkins/jnlp-slave:3.26-1

USER root
RUN apt update && apt install build-essential -y
USER jenkins

ENTRYPOINT ["jenkins-slave"]

這 Github 更新 Dockerfile 之後,Dockerhub 自動開始了建置映像檔的動作,我們可以上個廁所、泡泡茶再回來看看建置結果。

很好,這次成功了!

接下來就是啟動一個新的 agent,如果忘記的話可以參考 使用 Docker 安裝 Jenkins Agent

這次不同的是,標籤設定為 cpp,使用方式設為只保留給限定節點的作業,因為有些專案不需要 C++ 環境,所以我們為了區隔,讓這個 agent 只跑需要 C++ 的專案。

接著啟動 C++ Agent

docker run \
    --name jenkins_agent_cpp \
    -d --restart always \
    allyusd/jenkins-jnlp-slave-cpp \
    -url http://192.168.43.140:8080 \
    951ac478b69131e43fb2cfb6d201ecf789ba388a759ea946d7ab62aac55227a7 \
    agent-cpp

接著修改上一篇建立的 test_cpp 專案設定,選取限制專案執行節點,在標籤表示式輸入 cpp,按下儲存之後點擊馬上建置

這一次順利的建置成功啦!

留言