本文描述了如何将Jenkins代理节点(Jenkins Slave或Jenkins Agent)运行在Docker节点上,并通过JNLP协议在Jenkins Master和Docker节点间进行通讯。
在一台VM上,参见OneDayDevOps:一键部署DevOps平台一键安装Docker。
开启该Docker的远程访问API,使得Jenkins Master可以和Docker通讯。
修改/usr/lib/systemd/system/docker.service
,将ExecStart=/usr/bin/dockerd
改为:
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock
重新加载Docker配置和重启Docker:
systemctl daemon-reload
systemctl restart docker
systemctl status docker
开启防火墙端口:
firewall-cmd --zone=public --add-port=4243/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-all
在Docker节点上测试:
curl http://localhost:4243/version
在Jenkins Master上测试:
curl http://:4243/version
注意:如果该Docker节点暴露在外网环境,需要对允许访问的IP和credential做严格限制。
参考文档:
打开Manage Jenkins / Configure Global Security
在Agents下,选择 TCP port for JNLP agents为Fixed,输入一个端口号,比如46477
可以运行netstat -tnlp
查看该端口是否被占用。
打开该端口的防火墙设置:
firewall-cmd --zone=public --add-port=46477/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-all
确保Agent protocols勾选了Java Web Start Agent Protocol/4 (TLS encryption),也就是JNLP-4
安装Jenkins Docker插件
安装完Docker插件后,在Manage Jenkins下会多出一个Docker的菜单。
打开 Manage Jenkins / Configure System,找到Cloud。
选择Add a new Cloud,选择Docker
输入Name,比如docker
输入Docker Host URI为上一步的Docker节点URI,通讯协议为tcp
协议,比如tcp://192.168.87.111:4243
点击Test Connection测试Jenkins Master是否可以正常连接Docker节点。
勾选Enabled
在上一步配置Docker Cloud中,点击Add Docker Template。
输入Labels,比如docker-slave
(Jenkins Pipeline中将使用该label来选择Jenkins Agent)
勾选Enabled
输入Name,一般为镜像简短描述,比如jnlp-slave-with-java-build-tools
输入Docker Image,比如registry.cn-shenzhen.aliyuncs.com/cookcodeblog/jnlp-slave-with-java-build-tools:latest
这里使用了阿里云镜像仓库来加速下载cloudbees/jnlp-slave-with-java-build-tools镜像,参见:https://github.com/cookcodeblog/jenkins-docker-library
选择Remote File System Root为/home/jenkins
选择Usage为Only build jobs with label expressions matching this node
选择Connect method为Connect with JNLP
选择Pull strategy为Pull once and update latest
可选修改Idle timeout,缺省为10分钟
先检查和安装Docker Pipeline插件。
下面的Jenkins Pipeline例子将启动之前配置的docker-slave
的Docker模板的容器来作为Jenkins Agent(Jenkins Agent on Docker),并运行命令来检查git和maven的版本:
pipeline {
agent {label 'docker-slave'}
stages {
stage('Prepare') {
steps {
sh 'git --version'
sh 'mvn -v'
}
}
}
}
Jenkins Pipeline运行完后,该Jenkins Agent和对应的容器会被删除。
参考文档:
在Docker节点上创建Maven local repo并设置文件权限:
mkdir -p /var/lib/jenkins/.m2
chmod -R 777 /var/lib/jenkins/.m2
参照上面“配置Docker Agent Template”的步骤,点击“Container Settings“
输入Volumes: /var/lib/jenkins/.m2:/home/jenkins/.m2
这样在Jenkins Agent容器运行Maven构建时就可以共享Docker节点的本地Maven repo
复制settings.xml 到/var/lib/jenkins/.m2
来使用阿里云Maven mirror,或者使用含有私有Maven mirror的settings.xml
Jenkins Pipeline例子:
pipeline {
agent {label 'docker-slave'}
stages {
stage('Source') {
steps {
git branch: 'master', url: 'https://github.com/cookcodeblog/gs-rest-service.git'
}
}
stage('Build') {
steps {
sh 'mvn clean install'
}
}
}
}
在Jenkins左下角可以看到运行/空闲/Offline的Jenkins Agent,点击进去可以查看对应的容器ID。
也可以通过Manage Jenkins / Manage Nodes进去查看节点信息。
运行docker exec -it
可以进入正在运行的Jenkins Agent容器
运行docker logs -f
可以查看正在运行的Jenkins Agent容器的日志
在Manage Jenkins / Docker中可以查看容器运行的命令详情,在容器启动失败时,可以尝试手工启动来定位问题docker run jenkins/jnlp-slave -url http://jenkins-server:port
,比如:
docker run registry.cn-shenzhen.aliyuncs.com/cookcodeblog/jnlp-slave-with-java-build-tools:latest http://192.168.87.110:8080/ db7c8e61571d209e9f90ad9cc5efd0c99aea4e7938efa8b1b97f4cab58078e49 jnlp-slave-with-java-build-tools-00005t6weussx
在Docker节点上运行docker ps
查看运行的容器,运行docker ps -a
查看所有容器。
删除全部Docker容器:docker rm $(docker ps -a -q)。
https://devopscube.com/docker-containers-as-build-slaves-jenkins/
cloudbees/jnlp-slave-with-java-build-tools
https://github.com/jenkinsci/docker-jnlp-slave