问题:

docker部署完的jenkins无法使用docker-compose指令

前提:

docker run时已经挂载了docker以及docker-compose的目录,docker是最新的能使用最新的docker compose命令;Jenkins已经安装docker plugins以及docker compose plugin,但还是在编译时显示找不到docker-compose以及无法使用docker compose指令



排查过程

  1. 进入jenkins容器里查看docker版本,发现版本比挂载的版本低,怀疑被docker plugin版本覆盖?
  2. 使用docker compose和docker-compose命令,均发现可用
  3. docker plugin配置的路径无误

尝试过程:

  • 尝试一:
  1. 先用which docker-compose找到docker-compose路径(使用jenkins新建工程编写shell命令或进入jenkins容器内使用which命令查找)

  1. 再使用绝对路径下的docker-compose进行部署操作

结果: 绝对路径下使用docker-compose仍然失败,怀疑是由于宿主机和jenkins容器里版本不兼容。

  • 尝试二:
  1. docker run命令中把挂载docker的目录覆盖原本/usr/bin/docker目录,(-v /usr/bin/docker:/usr/local/docker \ 改为 -v /usr/bin/docker:/usr/bin/docker \)试图用宿主机的docker来使用最新的docker compose命令来跳过docker-compose命令的使用失败。
  2. chmod +x /usr/bin/docker 增加执行权限。
  3. 检查挂载是否生效,ls -l /var/run/docker.sock

结果: 失败,容器不支持高版本docker,导致原本的docker命令也使用不了,显示/usr/bin/docker: No such file or directory。后续取消挂载 /usr/bin/docker恢复正常。

  • 尝试三:
  1. 使用jenkins的cloud远程 Docker 守护进程,通过tcp使用宿主机的docker进行操作

结果:
失败,因为使用的是jenkinsci/blueocean,版本为2.346.3,一开始连插件库都用不了,后面用nginx反代了老版本插件库才能正常用,但是docker plugin版本太低并没有cloud,遂放弃。

  • 尝试四:
  1. jenkins里的docker plugin安装最新版本docker,失败,版本仍没有docker compose
  2. jenkins容器里安装docker,失败
1
2
apk update
apk add docker

结果:
失败,因为使用的是jenkinsci/blueocean,版本为2.346.3,一开始连插件库都用不了,后面用nginx反代了老版本插件库才能正常用,但是docker plugin版本太低并没有cloud,遂放弃。

  • 尝试五:
  1. docker run挂载docker-compose
  2. docker容器里安装docker-compose

结果:
失败,容器里尝试compose命令显示/usr/bin/docker-compose: /usr/bin/python3: bad interpreter: No such file or directory,使用apk add --no-cache python3安装python3后还是不行;
容器里安装docker-compose,curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose ,并执行chmod +x /usr/local/bin/docker-compose,后续补充完缺失的环境后还是不行,最后放弃并删除下载的docker-compose以及取消docker-compose的挂载。

  • 尝试六:
  1. 更新jenkins版本,下载官方war,进行覆盖
  2. 新版本jenkins得用jdk17更新,2.346.3 jdk为11,更新不了,尝试挂载jdk17,但因为jenkins容器的操作系统版本是Alpine Linux ,因为alpine用的是musl libc,而不是glibc
  3. 尝试进入jenkins容器里安装glibc
    1
    2
    3
    wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-2.33-r0.apk
    apk add glibc-2.33-r0.apk.
1
2
curl -Ls https://archive.archlinux.org/packages/z/zlib/zlib-1%3A1.2.9-1-x86_64.pkg.tar.xz -o libz.tar.xz && mkdir -p libz && tar -xf libz.tar.xz -C libz
mv libz/usr/lib/libz.so* /usr/glibc-compat/lib

结果:
失败,新版本jenkins得用jdk17更新,2.346.3 jdk为11,更新不了,尝试挂载jdk17,但因为jenkins容器的操作系统版本是Alpine Linux ,因为alpine用的是musl libc,而不是glibc。

  • 尝试七
  1. 最后还是选择更新jenkins版本,一劳永逸
  2. 登陆docker hub搜索jdk17版本的jenkins-lts,找到命令拉取镜像docker pull jenkins/jenkins:lts-jdk17,停止原来jenkins-blueocean容器,并docker run jdk17-lts,
  3. docker run \ -u root \ --name jenkins-lts \ -p 9090:8080 \ -p 50001:50000 \ -v jenkins-data:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ -v "$HOME":/home \ --restart=on-failure \ jenkins/jenkins:lts-jdk17
  4. 修改原来的反代链接回https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json,并点击更新在这里插入图片描述
  5. 更新所有可以更新的插件,着重docker plugin,更新好后重启jenkins

    点击clouds,选择new clouds
  6. 先回到宿主机,开启2375端口,vi /usr/lib/systemd/system/docker.service,增加ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --containerd=/run/containerd/containerd.sock,开启2375而不是2376是因为2375 和 2376,通常只用前者;后者是基于 TLS 连接,需要额外配置证书。
  7. 配置完后输入systemctl daemon-reload && systemctl restart docker重启服务,并在服务器开放相应端口,随后宿主机用curl http://localhost:2375/version测试是否能成功链接,成功后回到jenkins进行配置,成功后如图在这里插入图片描述

结果: 成功了一半,因为最后发现配置里实现比较局限,不如shell命令方便,所以考虑过后还是选择放弃该方法。

最终方案:

  1. 重新考虑新版本的jenkins是否能兼容宿主机的docker,重新对docker run命令进行改动,把/usr/bin/docker和/usr/bin/docker-compose加回去
  2. 进入容器实验之后发现docker可用,但是docker-compose还是不可用。在这里插入图片描述
  3. 应该已经兼容了新版本的docker,开始考虑是不是/usr/bin/docker-compose配置的路径有问题,在宿主机使用docker info命令查询docker-compose插件地址,发现地址并非usr/bin下而是/usr/libexec/docker/cli-plugins下在这里插入图片描述
  4. 于是更改docker run挂载地址,最后为docker run \ -u root \ --name jenkins-lts \ -p 9090:8080 \ -p 50001:50000 \ -v jenkins-data:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /usr/bin/docker:/usr/bin/docker \ -v /usr/libexec/docker/cli-plugins/docker-compose:/usr/bin/docker-compose \ -v "$HOME":/home \ --restart=on-failure \ jenkins/jenkins:lts-jdk17
  5. 进入容器后使用docker-compose -v命令进行测试发现已经能查询版本了

    结果: 终于成功,至此,终于可以使用docker-compose命令了。

总结

  1. 在宿主机使用docker info命令看docker-compose位置,在docker run jenkins时候挂载正确地址。
  2. 如果挂载正确地址还是无用考虑是否因为jeninks版本太老导致,可酌情考虑升级jenkins,但注意不同版本对jdk的支持不同。

ps.转载请注明出处