采用容器安装 Jenkins 的踩坑记录

为了方便管理容器的启动命令,统一使用 docker-compose 命令配合 docker-compose.yml 文件启动容器。基本使用可以 参考这里

关于如何在 Docker 中安装 Jenkins,参考这里

如果只是想看最终的 docker-compose.yml 文件,直接跳到最后一部分。

我的 CentOS7 的内核已经升级为 4.15,版本详情如下:

# uname -a
Linux VM_139_74_centos 4.15.6-1.el7.elrepo.x86_64 #1 SMP Sun Feb 25 20:57:32 EST 2018 x86_64 x86_64 x86_64 GNU/Linux

 

1. docker: not found

首先,要在 CentOS7 的容器中使用宿主机上的命令,需要在容器中使用 root 用户(也可以以 jenkins 用户运行,但是需要把容器内的 jenkins 用户加入到 docker 组中,通过 grep docker /etc/group 命令查看 docker 组的 GID)。

docker-compose.yml 示例文件如下:

version: '3'

services:
  jenkins-compose:
    image: jenkins
    user: root
    ports:
     - "8088:8080"
     - "50000:50000"
    volumes:
     - /var/run/docker.sock:/var/run/docker.sock
     - /home/demo/jenkins-compose:/var/jenkins_home

其中

  • user: root 表示在容器中以 root 用户运行
  • /var/run/docker.sock:/var/run/docker.sock 表示 Docker 守护进程监听的 Unix 套接字。要在 Jenkins 容器中使用 docker 命令,则此选项是必需的

然而,报错了:

/var/jenkins_home/workspace/first@tmp/durable-859cc63c/script.sh: 2: /var/jenkins_home/workspace/first@tmp/durable-859cc63c/script.sh: docker: not found

 

经过查找资料,要想在容器内使用宿主机的 docker 命令,有两种方法:

  • 为 Jenkins 容器添加特权,通过 -v 将宿主机的 docker 命令映射到容器,使其可以直接运行容器所在宿主机上的 docker 命令,称为 DooD。
  • 在 Jenkins 容器中安装 docker 称为 DioD。但是这样可能会导致莫名其妙的问题,不推荐,原因参考 这篇文章。如果要安装的话,可以参考 这里

上面的 docker-compose.yml 采用的就是第一种方法,需要通过 -v /usr/bin/docker:/usr/bin/docker 将宿主机的 docker 命令映射到容器。这里冒号前面的 /usr/bin/docker 表示宿主机上的 docker 命令的安装位置,如果你没有使用默认的安装位置,需要替换为你的实际位置。可以通过 which docker 查看 docker 命令的安装位置。

2. docker: Permission denied

修改后的 docker-compose.yml 示例文件如下:

version: '3'

services:
  jenkins-compose:
    image: jenkins
    user: root
    ports:
     - "8088:8080"
     - "50000:50000"
    volumes:
     - /var/run/docker.sock:/var/run/docker.sock
     - /usr/bin/docker:/usr/bin/docker
     - /home/demo/jenkins-compose:/var/jenkins_home

 

然而,再次报错:

/var/jenkins_home/workspace/first@tmp/durable-f92a2624/script.sh: 2: /var/jenkins_home/workspace/first@tmp/durable-f92a2624/script.sh: docker: Permission denied

 

在容器中使用 root 用户时需要给容器 分配 privileged 特权,这样容器中的 root 用户才可以具有和宿主机上 root 用户一样大的权限。可以通过下面的命令查看容器是否具有特权:

docker inspect --format='{{.HostConfig.Privileged}}' 你的容器的 ID

 

3. 找不到 libltdl.so.7

再次修改后的 docker-compose.yml 示例文件如下:

version: '3'

services:
  jenkins-compose:
    image: jenkins
    privileged: true
    user: root
    ports:
     - "8088:8080"
     - "50000:50000"
    volumes:
     - /var/run/docker.sock:/var/run/docker.sock
     - /home/demo/jenkins-compose:/var/jenkins_home
     - /usr/bin/docker:/usr/bin/docker

 

其中

  • privileged: true 表示当前容器具有特权

这次报错如下:

docker: error while loading shared libraries: libltdl.so.7: cannot open shared object file: No such file or directory

 

这个错误表示,Jenkins 所在的镜像可以执行 docker 命令了,但是还缺少执行 docker 命令所需的 library。此时有两个选择:

  • 将宿主机的 library 映射到容器
  • 在容器内安装缺少的 library

因为懒,不想创建中间镜像,同时也是想尽量使用官方的默认镜像,所以选择了方案一。在 CentOS7 上可能也没有安装这个 library,但是没关系,通过 yum install 命令即可轻松安装:

yum install libltdl.so.7

 

安装好后,查看安装位置,为使用卷做准备:

which libltdl.so.7

 

我这里的安装位置是:

/usr/lib64/libltdl.so.7

 

在 Jenkins 镜像中使用这个 library 的位置是 /usr/lib/x86_64-linux-gnu/libltdl.so.7,通过 -v 映射即可。

4. 完整分析

完整的报错内容如下:

Using sole credentials lihongfeng/****** in realm ‘<svn://111.230.25.113:3690> jenkins demo’
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/demo-pipeline
[Pipeline] {
[Pipeline] sh
[demo-pipeline] Running shell script
+ docker inspect -f . golang:1.10
/var/jenkins_home/workspace/demo-pipeline@tmp/durable-d5484068/script.sh: 2: /var/jenkins_home/workspace/demo-pipeline@tmp/durable-d5484068/script.sh: docker: not found
[Pipeline] sh
[demo-pipeline] Running shell script
+ docker pull golang:1.10
/var/jenkins_home/workspace/demo-pipeline@tmp/durable-3aaa5181/script.sh: 2: /var/jenkins_home/workspace/demo-pipeline@tmp/durable-3aaa5181/script.sh: docker: not found
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
ERROR: script returned exit code 127
Finished: FAILURE

 

实际上,通过

docker run -p 8080:8080 -p 50000:50000 privildged -v /var/run/docker.sock:/var/run/docker.sock jenkins

 

命令启动 Jenkins 时,-v /var/run/docker.sock:/var/run/docker.sock 就表示容器可以和 Docker 守护进程通信了,并且 Ubuntu 系列的 Linux 上没有问题(暂时没有在 Ubuntu 上面验证),但在 RedHat 系列(RHEL、CentOS、Fedora 等)的 Linux 上运行 docker 时会因为 SELinux 而报错 docker: not found。解决方案在 这里

5. 最终可用的 docker-compose.yml 文件

version: '3'

services:
  jenkins-compose:
    image: jenkins
    privileged: true
    user: root
    ports:
     - "8088:8080"
     - "50000:50000"
    volumes:
     - /var/run/docker.sock:/var/run/docker.sock
     - /usr/bin/docker:/usr/bin/docker
     - /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7
     - /home/demo/jenkins-compose:/var/jenkins_home

 

其中

  • image: jenkins 表示使用官方 Jenkins 仓库中的最新版本
  • privileged: true 表示当前容器具有特权
  • user: root 表示在容器内使用 root 用户
  • ports 表示端口映射
    • "8088:8080" 将宿主机的 8088 端口映射到容器的 8080 端口(Jenkins 默认监听 8080 端口)
    • "50000:50000" 只有在其他主机设置了一个或多个基于 JNLP 的 Jenkins 代理程序,而这些代理程序又与 jenkinsci/blueocean 容器(作为主 Jenkins 服务器“Jenkins master”)进行交互时才需要这个配置。
  • volumes 表示磁盘映射
    • /usr/bin/docker:/usr/bin/docker 表示将宿主机中的 docker 命令映射到容器中
    • /home/demo/jenkins-compose:/var/jenkins_home 表示将宿主机中的 /home/demo/jenkins-compose 目录映射到容器中,作为 Jenkins 的工作目录
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值