0. Jenkins构建Docker镜像的应用需求

由于micros整个工程分成多个组来共同开发。为了便于各个组进行测试,进行如下设计:

1) 各个组在gitlab上创建一个或者多个branch,jenkins为各组的branch创建一个job,并为job创建对应的build策略。

2) docker registry(私有仓库)里面存储了各个组的镜像

3) 各组进行源码修改的时候,提交到gitlab,同时还要包括一个dockerfile,说明基于哪个image,在该image基础上做了什么修改

4) 各组提交代码后,jenkins拉取提交的branch代码,并在jenkins服务器本地执行dockerfile,完成image的升级或者更新,然后根据job的build策略,执行build操作,生成一个新的镜像

5) job对应的build策略中,包含了将新镜像push到docker registry的操作

6) 查看仓库中是否有该镜像,如果有,则说明成功

7) 各组继续开发,可以基于上一次更新的image。

1. Jenins上创建一个job

前面几篇文章已经创建了gitlab,jenkins以及docker registry。本文基于上述基础。

这里,因为要构建docker镜像,而我们刚搭建jenkins还没有对应的docker可以使用。所以这里暂时用一个github上的项目作为构建docker的例子。将来我们自己的源码放到gitlab上之后,附上dockerfile,即可参考下述过程构建docker镜像。

然后创建一个自由风格的job为nginx。


然后配置一下源码管理,Git地址:https://github.com/dongwenpeng/nginx

打开git地址,发现里面有如下几个文件。有用的主要是dockerfile,其他的包括然后提供了一些nginx配置文件以及web文件。

-rw-r--r-- 1 jenkins jenkins    744 Dec 27 20:22 default.conf

-rw-r--r-- 1 jenkins jenkins    338 Dec 27 20:22 dockerfile

-rw-r--r-- 1 jenkins jenkins    593 Dec 27 20:22 nginx.conf

drwxr-xr-x 3 jenkins jenkins     16 Dec 27 20:22 web

-rw-r--r-- 1 jenkins jenkins 644118 Dec 27 20:22 web.zip
————————————————
版权声明:本文为CSDN博主「土豆西瓜大芝麻」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jinking01/article/details/85100065

如下配置,也可以使用你本地的Git仓库:

jenkins docker镜像 jenkins docker构建镜像发布_docker拉去jenkins镜像报错

主要就是构建脚本了,往下拉到build--add build step,选择执行shell,

jenkins docker镜像 jenkins docker构建镜像发布_docker_02

  添加如下内容:主要就是docker build所需要的参数,这里要注意docker所在的路径,可以先用whereis docker找一下。

jenkins docker镜像 jenkins docker构建镜像发布_docker拉去jenkins镜像报错_03

#!/bin/sh
#
DATE=`date +%m%d%H%M `
#DIR="/var/lib/jenkins/jobs/nginx/workspace/"
 DIR="."
sudo /usr/bin/docker build -t nginx_$DATE $DIR | tee $DIR/Docker_build_result.log
 
RESULT=$(cat $DIR/Docker_build_result.log | tail -n 1)
 
if [["$RESULT" != *Successfully*]];then
  exit -1
fi

配置结束后,保存。

2. 配置jenkins用户

此时还不能立即构建,因为jenkins触发脚本并不是root用户,因此需要将jenkins免密码,并将用户加入到docker组,否则获取不到容器ID.

nano/etc/sudoers

Defaults:jenkins !requiretty
# User privilege specification
root    ALL=(ALL:ALL) ALL
jenkins ALL=(ALL:ALL) ALL

 

sudo usermod -G docker jenkins

在Jenkins的使用过程中,如果在脚本中使用到sudo命令,有可能出现如下所示的错误:

sudo: no tty present and no askpass program specified

这是因为Jenkins服务器在执行sudo命令时的上下文有误,导致这个命令执行的异常。

先设置不需要tty:

jenkins docker镜像 jenkins docker构建镜像发布_Jenkins_04

在设置免密码:

在Jenkins宿主服务器上运行如下命令 
$ sudo visudo
修改jenkins权限
jenkins ALL=(ALL) NOPASSWD: ALL

jenkins docker镜像 jenkins docker构建镜像发布_Jenkins_05

然后重启jenkins 

/etc/init.d/jenkins restart

3. 开始构建镜像

在jenkins页面上对Nginx执行build。查看日志,由于jenkins会自动把github上的文件给下载下来放在workspace目录中。因此,触发脚本后,直接开始构建nginx镜像。

 如果前面配置都正确的话,应该会出现如下日志:

Started by user Administrator
Building in workspace /var/lib/jenkins/workspace/nginx
 > git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > git config remote.origin.url https://github.com/dongwenpeng/nginx # timeout=10
Fetching upstream changes from https://github.com/dongwenpeng/nginx
 > git --version # timeout=10
 > git fetch --tags --progress https://github.com/dongwenpeng/nginx +refs/heads/*:refs/remotes/origin/*
 > git rev-parse refs/remotes/origin/master^{commit} # timeout=10
 > git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10
Checking out Revision c0148c6714be8a64710d87e2ebc3395573dfcb0f (refs/remotes/origin/master)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f c0148c6714be8a64710d87e2ebc3395573dfcb0f
Commit message: "docker images"
 > git rev-list --no-walk c0148c6714be8a64710d87e2ebc3395573dfcb0f # timeout=10
[nginx] $ /bin/sh /tmp/jenkins5804040439588409846.sh
Sending build context to Docker daemon 3.273 MB

Step 1/13 : FROM nginx
 ---> 568c4670fa80
Step 2/13 : MAINTAINER dkey
 ---> Using cache
 ---> 60c5a8a4fb14
Step 3/13 : ENV RUN_USER nginx
 ---> Using cache
 ---> 738cd2e26361
Step 4/13 : ENV RUN_GROUP nginx
 ---> Using cache
 ---> fca704beccc4
Step 5/13 : ENV DATA_DIR /data/web
 ---> Using cache
 ---> 575a52d71bc0
Step 6/13 : ENV LOG_DIR /data/log/nginx
 ---> Using cache
 ---> 9e8839af5617
Step 7/13 : RUN mkdir /data/log/nginx -p
 ---> Using cache
 ---> 094ea8870679
Step 8/13 : RUN chown nginx.nginx -R /data/log/nginx
 ---> Using cache
 ---> 2349737938f7
Step 9/13 : ADD web /data/web
 ---> Using cache
 ---> 75c536901319
Step 10/13 : ADD nginx.conf /etc/nginx/nginx.conf
 ---> Using cache
 ---> f066c262603e
Step 11/13 : ADD default.conf /etc/nginx/conf.d/default.conf
 ---> Using cache
 ---> b4bffccbda9c
Step 12/13 : EXPOSE 80
 ---> Using cache
 ---> d7ce75f2e7ba
Step 13/13 : ENTRYPOINT nginx -g "daemon off;"
 ---> Using cache
 ---> af92f977e45b
Successfully built af92f977e45b
/tmp/jenkins5804040439588409846.sh: 10: /tmp/jenkins5804040439588409846.sh: [[Successfully built af92f977e45b: not found
Finished: SUCCESS

查看镜像是否创建成功: 

 

jenkins docker镜像 jenkins docker构建镜像发布_Docker_06

5. 推送到远程仓库

现在使用Jenkins构建Docker镜像已经没有问题了,下面就可以把Jenkins构建完的镜像直接推送到远程的registry中

push image的时候如果出现下面的错误:

FATA[0000] Error: v1 ping attempt failed with error: Get https://192.168.8.40:5000/v1/_ping: dial tcp 192.168.8.40:5000: connection refused.

则需要在执行push命令的机器上配置docker:

jenkins docker镜像 jenkins docker构建镜像发布_docker拉去jenkins镜像报错_07

查看私有仓库里的镜像(从公网看不到)

root@taiic:/var/lib# curl -X GET http://127.0.0.1:5000/v2/_catalog
{"repositories":["nginx_1"]}
这是在docker registry服务器上查看私有仓库里的镜像

micros@taiic:/etc/init.d$ curl -XGET http://192.168.8.40:5000/v2/_catalog
{"repositories":["centos-test","micros-env"]}
在远程机器上可以用这个命令查看私有仓库里有哪些镜像。

6. 设置自动push镜像

修改job的配置中的build中的shell脚本:

#!/bin/sh
#
DATE=`date +%m%d%H%M `
#DIR="/var/lib/jenkins/jobs/nginx/workspace/"
 DIR="."
sudo /usr/bin/docker build -t nginx_$DATE $DIR | tee $DIR/Docker_build_result.log
 
RESULT=$(cat $DIR/Docker_build_result.log | tail -n 1)

 
if [["$RESULT" != *Successfully*]];then
  exit -1
fi
#后面是打tag和push操作
echo '>>> Add tag to the new image'
sudo /usr/bin/docker tag nginx_$DATE	192.168.8.40:5000/nginx_$DATE

echo '>>> Start push new image'

sudo /usr/bin/docker push 192.168.8.40:5000/nginx_$DATE

日志如下: 

Started by user Administrator
Building in workspace /var/lib/jenkins/workspace/nginx
 > git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > git config remote.origin.url https://github.com/dongwenpeng/nginx # timeout=10
Fetching upstream changes from https://github.com/dongwenpeng/nginx
 > git --version # timeout=10
 > git fetch --tags --progress https://github.com/dongwenpeng/nginx +refs/heads/*:refs/remotes/origin/*
 > git rev-parse refs/remotes/origin/master^{commit} # timeout=10
 > git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10
Checking out Revision c0148c6714be8a64710d87e2ebc3395573dfcb0f (refs/remotes/origin/master)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f c0148c6714be8a64710d87e2ebc3395573dfcb0f
Commit message: "docker images"
 > git rev-list --no-walk c0148c6714be8a64710d87e2ebc3395573dfcb0f # timeout=10
[nginx] $ /bin/sh /tmp/jenkins6632556266194448186.sh
Sending build context to Docker daemon 3.273 MB

Step 1/13 : FROM nginx
 ---> 568c4670fa80
Step 2/13 : MAINTAINER dkey
 ---> Using cache
 ---> 60c5a8a4fb14
Step 3/13 : ENV RUN_USER nginx
 ---> Using cache
 ---> 738cd2e26361
Step 4/13 : ENV RUN_GROUP nginx
 ---> Using cache
 ---> fca704beccc4
Step 5/13 : ENV DATA_DIR /data/web
 ---> Using cache
 ---> 575a52d71bc0
Step 6/13 : ENV LOG_DIR /data/log/nginx
 ---> Using cache
 ---> 9e8839af5617
Step 7/13 : RUN mkdir /data/log/nginx -p
 ---> Using cache
 ---> 094ea8870679
Step 8/13 : RUN chown nginx.nginx -R /data/log/nginx
 ---> Using cache
 ---> 2349737938f7
Step 9/13 : ADD web /data/web
 ---> Using cache
 ---> 75c536901319
Step 10/13 : ADD nginx.conf /etc/nginx/nginx.conf
 ---> Using cache
 ---> f066c262603e
Step 11/13 : ADD default.conf /etc/nginx/conf.d/default.conf
 ---> Using cache
 ---> b4bffccbda9c
Step 12/13 : EXPOSE 80
 ---> Using cache
 ---> d7ce75f2e7ba
Step 13/13 : ENTRYPOINT nginx -g "daemon off;"
 ---> Using cache
 ---> af92f977e45b
Successfully built af92f977e45b
/tmp/jenkins6632556266194448186.sh: 11: /tmp/jenkins6632556266194448186.sh: [[Successfully built af92f977e45b: not found
>>> Add tag to the new image
>>> Start push new image
The push refers to a repository [192.168.8.40:5000/nginx_12200935]
4faf5dee2b80: Preparing
3b66c7dfdf1e: Preparing
111a6440378f: Preparing
5885cdf2cd45: Preparing
55a89fa43054: Preparing
ece4f9fdef59: Preparing
ad5345cbb119: Preparing
ef68f6734aa4: Preparing
ece4f9fdef59: Waiting
ef68f6734aa4: Waiting
55a89fa43054: Pushed
5885cdf2cd45: Pushed
3b66c7dfdf1e: Pushed
4faf5dee2b80: Pushed
ece4f9fdef59: Pushed
111a6440378f: Pushed
ad5345cbb119: Pushed
ef68f6734aa4: Pushed
latest: digest: sha256:744c3675dd95675e9b0a3c7bc24db13d8685878e3f74a14701596d1d16faeb94 size: 1986
Finished: SUCCESS

查看镜像:

jenkins docker镜像 jenkins docker构建镜像发布_Docker_08

 

查看仓库:

jenkins docker镜像 jenkins docker构建镜像发布_Jenkins_09

成功。至此使用jenkins构建docker镜像并自动上传到docker registry仓库的配置过程结束。 

每次使用的时候要确保registry这个镜像已经运行起来了,否则相当于仓库没有开始营业,就无法push镜像到仓库。

附:dockerfile的内容: 

FROM nginx
MAINTAINER dkey
ENV RUN_USER nginx
ENV RUN_GROUP nginx
ENV DATA_DIR /data/web
ENV LOG_DIR /data/log/nginx
RUN mkdir /data/log/nginx -p
RUN chown nginx.nginx -R /data/log/nginx
ADD web /data/web
ADD nginx.conf /etc/nginx/nginx.conf
ADD default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
ENTRYPOINT nginx -g "daemon off;"

其实就是根据一个基础镜像Nginx,执行一些操作,主要是将本地的一些文件复制到docker镜像里面,然后再build成一个新的镜像。