I have created a Dockerfile (for a Node JNLP slave which can be used with the Kubernetes Plugin of Jenkins ). I am extending from from the official image jenkinsci/jnlp-slave
FROM jenkinsci/jnlp-slave
USER root
MAINTAINER Aryak Sengupta <aryak.sengupta@hyland.com>
LABEL Description="Image for NodeJS slave"
COPY cert.crt /usr/local/share/ca-certificates
RUN update-ca-certificates
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash \
&& apt-get install -y nodejs
ENTRYPOINT ["jenkins-slave"]
I have this image saved inside my Pod template (in K8s plugin configuration). Now, when I'm trying to run a build on this slave, I find that two containers are getting spawned up inside the Pod (A screenshot to prove the same.).
My Pod template looks like this:
And my Kubernetes configuration looks like this:
Now if I do a simple docker ps
, I find that there are two containers which started up (Why?):
Now, inside the Jenkins Job configuration of Jenkins, whatever I add in the build step, the steps get executed in the first container .
Even if I use the official Node
container inside my PodTemplate
, the result is still the same:
I have tried to print the Node version inside my Jenkins Job, and the output is "Node not found" . Also, to verify my haunch, I have done a docker exec
into my second container and tried to print the Node
version. In this case, it works absolutely fine.
This is what my build step looks like:
So, to boil it down, I have two major questions:
Node
using this configuration?What am I missing?
P.S. - Please do let me know if the question turns out to be unclear in some parts.
Edit: I understand that this can be done using the Pipeline
Jenkins plugin where I can explicitly mention the container
name, but I need to do this from the Jenkins UI. Is there any way to specify the container name along with the slave name which I am already doing like this:
To set Container Template -> Name as jnlp. https://issues.jenkins-ci.org/browse/JENKINS-40847
The Jenkins kubernetes plugin will always create a JNLP slave container inside the pod that is created to perform the build. The podTemplate is where you define the other containers you need in order to perform your build.
In this case it seems you would want to add a Node container to your podTemplate. In your build you would then have the build happen inside the named Node container.
You shouldn't really care where the Pod runs. All you need to do is make sure you add a container that has the resources you need (like Node in this case). You can add as many containers as you want to a podTemplate. I have some with 10 or more containers for steps like PMD, Maven, curl, etc.
I use a Jenkinsfile with pipelines.
podTemplate(cloud: 'k8s-houston', label: 'api-hire-build',
containers: [
containerTemplate(name: 'maven', image: 'maven:3-jdk-8-alpine', ttyEnabled: true, command: 'cat'),
containerTemplate(name: 'pmd', image: 'stash.company.com:8443/pmd:pmd-bin-5.5.4', alwaysPullImage: false, ttyEnabled: true, command: 'cat')
],
volumes: [
persistentVolumeClaim(claimName: 'jenkins-pv-claim', mountPath: '/mvn/.m2nrepo')
]
)
{
node('api-hire-build') {
stage('Maven compile') {
container('maven') {
sh "mvn -Dmaven.repo.local=/mvn/.m2nrepo/repository clean compile"
}
}
stage('PMD SCA (docker)') {
container('pmd') {
sh 'run.sh pmd -d "$PWD"/src -f xml -reportfile "$PWD"/target/pmd.xml -failOnViolation false -rulesets java-basic,java-design,java-unusedcode -language java'
sh 'run.sh pmd -d "$PWD"/src -f html -reportfile "$PWD"/target/pmdreport.html -failOnViolation false -rulesets java-basic,java-design,java-unusedcode -language java'
sh 'run.sh cpd --files "$PWD"/src --minimum-tokens 100 --failOnViolation false --language java --format xml > "$PWD"/target/duplicate-code.xml'
}
archive 'target/duplicate-code.xml'
step([$class: 'PmdPublisher', pattern: 'target/pmd.xml'])
}
}
}
Alright so I've figured out the solution. mhang li's answer was the clue but he didn't explain it one bit.
Basically, you need to modify the official Jenkins Slave image found here and modify it to include the changes for your slave as well. Essentially, you are clubbing the JNLP and Slave containers into one and building a combined image.
The modification format will just look like this (picking up from the Dockerfile linked)
FROM jenkins/slave:3.27-1
MAINTAINER Oleg Nenashev <o.v.nenashev@gmail.com>
LABEL Description="This is a base image, which allows connecting Jenkins agents via JNLP protocols" Vendor="Jenkins project" Version="3.27"
COPY jenkins-slave /usr/local/bin/jenkins-slave
**INCLUDE CODE FOR YOUR SLAVE. Eg install node, java, whatever**
ENTRYPOINT ["jenkins-slave"] # Make sure you include this file as well
Now, name the slave container jnlp
(Reason - bug). So now, you will have one container that spawns which will be your JNLP + Slave. All in all, your Kubernetes Plugin Pod Template will look something like this. Notice the custom url to the docker image I have put in. Also, make sure you don't include a Command To Run
unless you need one.
Done! Your builds should now run within this container and should function exactly like you programmed the Dockerfile!