Docker installs Jenkins and supports maven, docker and helm

Time:2020-10-23

It is very simple to install Jenkins with docker. However, the installed Jenkins does not directly support the common CI tools such as Maven and docker. In particular, docker involvesRunning docker in dockerThat is to saydocker in dockerThis article will show how to solve the problem

Host computer of this sample Institutettg12The environment is as follows:

  • IP: 192.168.31.12,
  • OS: Ubuntu Server 18.04,
  • Docker version: 19.03.6

Students in a hurry can jump to the last section 4

1、 Docker install Jenkins

Jenkins is also divided into long-term support Version (LTS) and general support version. For those who need online long-term stable support, it is better to download the LTS version2.235.1-lts.

#Download Image
sudo docker pull jenkins/jenkins:2.235.1-lts
#Create a new container and start it
sudo docker run -d -p 8081:8080 -p 50001:50000 \
    -v /data2/jenkins/jenkins_home:/var/jenkins_home \
    -v /etc/localtime:/etc/localtime:ro \
    --restart=always \
    --name dao_jenkins_1 \
    jenkins/jenkins:2.235.1-lts

Two of them are described as follows

  • -v /data2/jenkins/jenkins_home:/var/jenkins_home, docker/var/jenkins_homeIs Jenkins’s $home and all configuration, data storage place, so it must be persisted locally
  • -v /etc/localtime:/etc/localtime:ro, keep the time zone in docker consistent with host, otherwise the log time will use UTC + 0 time zone, which is 8 hours different from China time

To view the container log:

sudo docker logs dao_jenkins_1

Display permission error:

touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?

This is because Jenkins is the current user on the hostfaceless, and the host local directory/data2/jenkins/jenkins_homebelong toroot.

The simple solution is to/data2/jenkins/jenkins_homeThe owner of is changed to the docker user running on the hostfaceless (uid=1000)

#Modify faceless to the user running docker on the host
sudo chown -R faceless /data/jenkins/jenkins_home 
# sudo chown -R faceless /var/run/docker.sock
sudo docker start dao_jenkins_1

Then restart the Jenkins containerdao_jenkins_1

sudo docker restart dao_jenkins_1

2、 Support docker

If we run Jenkins in the container, and Jenkins CI also needs to run docker, we will encounterdocker in dockerPlease refer to: ~ jpetazzo / using docker in docker for your CI or testing environment? Think twice

As we know, docker is actually divided into two parts: the server and the client. The server receives commands from the client through socket socket or listening port. For details, please refer to the official document configure where the docker daemon listen for connections

In other words, if we run the docker server on the host, we can only install the docker client in the container, and then use theSocket socketperhapsIP + portTo create a new container in the container is actually to create a new container on the host

Because the docker server and client use socket socket for interaction by default, we also use socket socket hereSocket socketThe solution is to host the host’s/var/run/docker.sockBy mapping toJenkinsContainers

2.1 let the container use the docker of the host

According to the above idea, we are creating thedocker runAdd the following three parameters to the command:

-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker 
-v /etc/docker:/etc/docker \

Explanation of the three

  • -v /var/run/docker.sock:/var/run/docker.sockBy mapping the socket file of the host to the container, the container in the container is not started when the docker is started(Sub container)Instead, start the container on the host(Brother container).
  • -v /usr/bin/docker:/usr/bin/dockerLet the container use the docker client of the host directly
  • -v /etc/docker:/etc/docker, let the docker client in the container use the docker configuration file of the host, including the configuration of domestic mirrors and non SSL security access white list

2.2 solve the problem of access to the host socket

After rebooting the container, we pass thedocker exec -it dao_jenkins_1 /bin/bashThe command enters the container and executesdocker psVerify whether the docker command can be used normally. The following permission problems are found:

[email protected]:/$ 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

Let’s take a look at host first/var/run/docker.sockPermissions for:

[email protected]:~$ ll /var/run/docker.sock
srw-rw---- 1 root docker 0 Jul 16 10:17 /var/run/docker.sock=

You can seedocker.sockbelong torootUsers anddockerGroup. The permissions mapped to the container are:

[email protected]:/$ ls -al /var/run/docker.sock
srw-rw---- 1 root 128 0 Jul 16 10:17 /var/run/docker.sock

Let’s check the Jenkins user ID and groupd ID in the container

[email protected]:/$ id
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins)

We can see that Jenkins has a user ID of 1000 and a group ID of 1000

  • Change the owner of the socket file touser id = 1000Users of;
  • Add users in the containergroup id = 128The authority of

The following are explained separately

2.2.1 modify host socket file permission settings

Change the owner of docker socket on the host to the user running uid = 1000, or directly change the permission to be readable and writable by others666:

#Modify the owner of the socket on the host to the user with id = 1000
sudo chown 1000 /var/run/docker.sock
#Or modify the permission of sock to 666
sudo chmod 666 /var/run/docker.sock

This scheme does not need to restart the container and runs directly inside the containerdocker psIt can be seen that normal results can be output

This scheme is given by most articles on the Internet. However, there is a comparison of the schemedefectIf the host or docker is restarted, it will be re createddocker.sockFile whose owner is reset torootUsers, so we need to execute the above command to modify permissions

2.2.2 give container docker group permission

The second solution is to add group permissions with id = 128 to Jenkins users in the containerdocker runVery friendlygroupd-addParameter supports this operation

Official documents additional groups

–group-add: Add additional groups to run as
By default, the docker container process runs with the supplementary groups looked up for the specified user. If one wants to add more to that list of groups, then one can use this flag:

$ docker run –rm –group-add audio –group-add nogroup –group-add 777 busybox id

uid=0(root) gid=0(root) groups=10(wheel),29(audio),99(nogroup),777

That is to say, we can pass one by onegroup-addParameter to add multiple additional user group permissions to the users in the container through group name or group ID. note: this user group refers to the user group in the container, and its ID may be inconsistent with the ID of the host. If we want the user in the container to have a certain group permission of the host, we need to empower it through the ID

So let’s first look at the ID of the docker group on the host

[email protected]:~$ cat /etc/group | grep docker
[sudo] password for faceless:
docker:x:128:faceless

You can see that the docker user group ID is 128. Therefore, we add the--group-add=128In the containerjenkinsUser owned/var/run/docker.sockRead and write permissions for the file:

#Remove the old container first
sudo docker rm -f dao_jenkins_1
#Recreate container
sudo docker run -d -p 8081:8080 -p 50001:50000 \
    -v /data2/jenkins/jenkins_home:/var/jenkins_home \
    -v /etc/localtime:/etc/localtime:ro \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /etc/docker:/etc/docker \
    -v /usr/bin/docker:/usr/bin/docker \
    --restart=always  \
    --group-add=128 \
    --name dao_jenkins_1 \
    jenkins/jenkins:2.235.1-lts

3、 Install additional CI tools

3.1 installing and configuring maven

First install Maven:

mkdir -p /opt/ && \
    cd /opt/ && \
    curl -fsSL https://mirror.bit.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz >    /tmp/apache-maven-3.6.3-bin.tar.gz && \
    tar xzf /tmp/apache-maven-3.6.3-bin.tar.gz -C /opt/ && \
    rm /tmp/apache-maven-3.6.3-bin.tar.gz && \
    ln -s /opt/apache-maven-3.6.3/bin/mvn /bin/mvn && \
    ln -s /opt/apache-maven-3.6.3/bin/mvnyjp /bin/mvnyjp && \
    export PATH=/opt/apache-maven-3.6.3/bin:$PATH

Then configure and accelerate Maven:
1) In the host directory/data2/jenkins/jenkins_home/(corresponding to docker’s/var/jenkins_home/)Open or new in.m2/settings.xmlFile, add alicloud image:

  <mirrors>
    <mirror>
      <id>ali-public</id>
      <mirrorOf>public</mirrorOf>
      <name>aliyun maven public</name>
      <url>https://maven.aliyun.com/repository/public</url>
    </mirror>
    <mirror>
      <id>ali-central</id>
      <mirrorOf>central</mirrorOf>
      <name>aliyun maven central</name>
      <url>https://maven.aliyun.com/repository/central</url>
    </mirror>
        <mirror>
      <id>aligoogle</id>
      <mirrorOf>google</mirrorOf>
      <name>aliyun google</name>
      <url>https://maven.aliyun.com/repository/google</url>
    </mirror>
        <mirror>
      <id>alisping</id>
      <mirrorOf>spring</mirrorOf>
      <name>aliyun spring</name>
      <url>https://maven.aliyun.com/repository/spring</url>
    </mirror>
        <mirror>
      <id>alispringplugin</id>
      <mirrorOf>spring-plugin</mirrorOf>
      <name>aliyun spring-plugin</name>
      <url>https://maven.aliyun.com/repository/spring-plugin</url>
    </mirror>
  </mirrors>

2) You can even copy all the downloaded three-party libraries in the local repository.m2/repository, save download time

3.2 support for kubernetes Helm

The support for kubernetes helm3 is relatively simple. You can directly map the helm on the host to the container. Note that this is for helm3, because tiller has been removed from helm3, only the client is needed

First copy the. Kube / config file on the k8s master to the docker host (here isttg12)Of/data2/jenkins/jenkins_home/.kube/Directory

And then in thedocker runAdd the following mapping to the command and rebuild the container

-v /usr/local/bin/helm:/bin/helm

3.3 commit changes to new image

After docker CE is installed, submit the update to a new image, and then start the container from this image:

#Submit modification
sudo docker commit -a "[email protected]" -m "jenkins v2.235.1-lts with support for maven, docker & k8s" dao_jenkins_1 jenkins_with_dockercli:2.235.1-lts

#Stop and remove the old container
sudo docker rm -f dao_jenkins_1

#Start a new container with a new image
sudo docker run -d -p 8081:8080 -p 50001:50000 \
    -v /data2/jenkins/jenkins_home:/var/jenkins_home \
    -v /etc/localtime:/etc/localtime:ro \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /etc/docker:/etc/docker \
    -v /usr/bin/docker:/usr/bin/docker \
    -v /usr/local/bin/helm:/bin/helm \
    --restart=always  \
    --group-add=128 \
    --name dao_jenkins_1 \
    jenkins_with_dockercli:2.235.1-lts

If necessary, you can push the image to the private docker registry

docker login --username=<your-useranme> registry.cn-hangzhou.aliyuncs.com
docker tag jenkins_with_dockercli:2.235.1-lts registry.cn-hangzhou.aliyuncs.com/faceless/jenkins_with_dockercli:2.235.1-lts
docker push registry.cn-hangzhou.aliyuncs.com/faceless/jenkins_with_dockercli:2.235.1-lts

If it is a development or test environment, it is recommended to use docker registry to build a local simple image service, which can improve efficiency and save time. For information on how to build a local image service, please refer to my other blog post about privatizing and deploying minimalist docker registry

4、 Scheme summary

In order to facilitate future expansion, I uploaded the image dockerfile of Jenkins + Maven to gitee Jenkins docker plus. Interested students can download it directly. You are also welcome to submit a new Jenkins + XX PR for improvement

Finally, we summarize the solutions obtained step by step. Docker installs Jenkins and supports maven, docker and helm

  1. Install docker CE on the host and configure the domestic image;
  2. Install k8s kubectl and helm3 on the host and complete the relevant configuration
  3. Download from gitee Jenkins docker plusjenkins-maven/DockerfileFile to host~/tmp/jenkins-maven/Dockerfile;
  4. get into`~/tmp/jenkins-maven/implementsudo docker build -t jenkins-maven:2.235.1-lts .Build a mirror image;
  5. View localdockerUser group ID:cat /etc/group | grep dockerUse < docker_ groupd_ ID > indicates the docker user group ID
  6. Configure parameters such as volumn mapping and user group, create and start Jenkins docker:

    #In this example: 
    # <host_jenkins_home> = $HOME/jenkins_home
    # <docker_groupd_id> = 128
    
    mkdir -p <host_jenkins_home>
    sudo docker run -d -p 8081:8080 -p 50001:50000 \
        -v <host_jenkins_home>:/var/jenkins_home \
        -v /etc/localtime:/etc/localtime:ro \
        -v /var/run/docker.sock:/var/run/docker.sock \
        -v /etc/docker:/etc/docker \
        -v /usr/bin/docker:/usr/bin/docker \
        -v /usr/local/bin/helm:/bin/helm \
        --restart=always  \
        --group-add=<docker_groupd_id> \
        --name dao_jenkins_1 \
        jenkins-maven:2.235.1-lts
  7. Visit http: / / < host_ IP >: 8081, enter Jenkins for initialization configuration
  8. Please refer to the “Maven” and “Maven” configuration on the host.seetings.xmlMake Maven acceleration

5、 Appendix

reference material:

  • Installing Jenkins with docker
  • Installing docker in Jenkins container
  • ~jpetazzo/Using Docker-in-Docker for your CI or testing environment? Think twice.
  • Docker run official document

Recommended Today

CentOS install Chinese Fonts

preface When we encounter some Chinese display garbled problems, it may be because the server does not install Chinese fonts install 1. View system fontsBefore starting the installation, we first check the installed fonts in the system. To view the installed fonts in the system, we can use thefc-listIf there is no command in the […]