安装jenkins有两种方式,一种是直接安装在centos这类的linux实体机中,一种是docker安装。使用普通功能的时候差不不大,但是当要调用外部命令的时候,因为docker一般环境不健全会有很多坑需要踩。比如本文涉及的docker中运行docker命令。、
应该以怎样的形式运行
问题1:docker中是否可以运行docker
答:可以,也就是docker in docker,但是很少见有人用
问题2:如果docker中不运行docker,是否可以执行docker命令。
答:可以,把宿主机的docker.sock文件和docker程序 映射到容器内部就可以
本文使用的就是把socket文件映射到容器内部的方式,因为这样可以共享宿主机的docker已经下载的镜像。
会出现的错误
错误1 提示找不到docker命令
如果没有把docker文件映射到内部,而直接在jenkins的构建过程的shell脚本中调用docker命令,或者是进入容器内部调用docker,提示没找不到docker命令。**
bash: docker: command not found
解决方案,映射宿主机docker程序到jenkins容器中。命令如下
docker run --name jenkins -d -p 8080:8080 -p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
-v /usr/bin/docker:/usr/bin/docker \
jenkins/jenkins:lts
错误2:容器内部运行docker ps或其他命令会提示
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
解决方案:映射宿主机socket到jenkins容器中。命令如下:
docker run --name jenkins -d -p 8080:8080 -p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
-v /usr/bin/docker:/usr/bin/docker \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkins/jenkins:lts
错误3:容器内部运行docker ps或其他命令会提示
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/json: dial unix /var/run/docker.sock: connect: permission denied
解决方案:明显就是无权限,socket文件一般只有root或者具有sudo权限的用户有访问权限,如果不想使用sudo就要创建一个docker组,这个组中的用户也可以访问。这里我们先查看容器内部权限:
srw-rw---- 1 root 994 0 Jul 14 05:50 /var/run/docker.sock
可以看到这是root用户,994组拥有rw权限。根据docker的原理来说,docker中的用户id和组id与宿主机的是一致的。使用cat /etc/group命令查看宿主机的组发现994的组就是docker组。
docker exec -it -u root jenkins bash
然后把jenkins加入到docker组中(如果容器中有docer组且组id与宿主机的相同的情况)
先用
cat /etc/group|grep 994
假设994也是docker组,则执行以下命令
usermod -G docker jenkins
再次运行已经可以了
如果容器内部没有组id是这个994的组(注意不是看名称是看groupid-组id),我们可以通过命令创建一个组,指定其groupid为994.
groupadd -g 994 docker1
然后
usermod -G docker1 jenkins
完成以后,重启jenkins容器生效
docker restart jenkins
当然如果你懒 直接chmod 777 也可以,但是出于安全考虑不建议这样做。
错误4:找不到lib
error while loading shared libraries: libltdl.so.7: ca directorynnot open shared object file: No such file or
解决方案,映射宿主机的lib路径到容器中。命令如下:
docker run --name jenkins -d -p 8080:8080 -p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
-v /usr/bin/docker:/usr/bin/docker \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7 \
jenkins/jenkins:lts
最终命令
docker run --name jenkins -d -p 8080:8080 -p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
-v /usr/bin/docker:/usr/bin/docker \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7 \
jenkins/jenkins:lts
命令详解
映射socket文件 : -v /var/run/docker.sock:/var/run/docker.sock :
映射docker程序 :-v /usr/bin/docker:/usr/bin/docker
映射需要的lib文件 :-v /usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7 jenkins/jenkins:lts
其他的是映射端口和工作目录。
附
这里附上docker 手册上的一句话,这也是解决这个问题的参考
Manage Docker as a non-root user
The docker daemon binds to a Unix socket instead of a TCP port. By default that Unix socket is owned by the user root and other users can only access it using sudo. The docker daemon always runs as the root user.
If you don’t want to use sudo when you use the docker command, create a Unix group called docker and add users to it. When the docker daemon starts, it makes the ownership of the Unix socket read/writable by the docker group.