自动化构建生产环境下的 Docker 镜像

Posted by ShenHengheng on 2018-11-11

本教程将会学习如何配置 Jenkins 来基于 Dockerfile 构建的 Docker 镜像,和如何使用 Docker 来实现(CICD)持续集成与开发。使用自动化镜像构建,在企业生产环境下将可以完成高效的升级与部署。

说明: 本教程借鉴于 katacoda 创建的关于CICD的教程.

这次教程主要我尝试了两个版本:

  • 宿主机是 x86 架构的系统(系统:Ubuntu,Arch)
  • 宿主机是 给予Arm 的系统(树莓派,系统为Hypriot)

Linux下部署安装

环境准备

三种安装部署方案

三种安装部署方案

说明:这三种方案均测试过,大家可以从图中看到方案2可能是生产中所使用到的方案,方案 1 较为冗余,比较传统, 方案三是我本次教程所要使用的部署方案。

是用这三种方案都需要安装 Docker, 并提供一个供外部访问的 REST API 守护程序(Docker daemon), 类似于 kubernetes 的 kube-api-server一样。在 ubuntu 和 Hyproiot 中需要这样操作:

sudo mkdir -pv /etc/systemd/system/docker.service.d
cat << EOF > /etc/systemd/system/docker.service.d/remote-api.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

可以使用下面的命令测试

# 查看端口是否打开
netstat -an | grep 2375
ss -ntlp | grep 2375
# 检查守护程序能否正常工作
docker -H  172.16.3.16:2375 info

简便方法:可以直接是用下面命令启动守护程序,但在生产中是不允许的。

# listen using the default unix socket, and on 2 specific IP addresses on this host.
$ sudo dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375

启动 Jenkins

首先创建一个数据卷,用来保存 Jenkins 安装的插件。

docker create -v /data --name jenkinsdata busybox

使用下面的命令启动一个 Jenkins 的docker容器,并关联/挂着到之前创建的数据卷。此时 Jenkins 容器中所有插件和配置文件都将会持久化到我们的 jenkinssdata 这个数据卷中。

docker run -d -u root --name jenkins \
    -p 8080:8080 -p 50000:50000 \
    --volumes-from jenkinsdata\
    --restart always \
    jenkins/jenkins:2.112-alpine

注意: 当然可以直接挂载到指定的宿主机上的目录

启动Jenkins 仪表盘

可以通过访问 http://172.16.3.32:8080/ 来访问 Jenkins 的仪表板

login page

login page

这里需要输入 admin 的密码,密码是随机的,需要通过下面的命令查看初始密码。

docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword

Jenkins 可能需要几秒钟才能完成启动。在接下来的步骤中,将使用仪表板配置插件并开始构建Docker镜像。

安装与配置插件

第一步是配置 Docker 插件。该插件基于 Jenkins Cloud 插件。当构建需要 Docker 时,它将通过插件创建“Cloud Agent”。代理将是一个 Docker 容器,需要经过配置与我们的前面配置的 Docker 守护进程通信。

安装

  • 在仪表板中,选择左侧的 系统管理。
  • 在“管理Jenkins”页面上,选择“管理插件”。
  • “管理插件”页面将为您提供选项卡式界面。单击“可选插件”以查看可以安装的所有Jenkins插件。
  • 使用搜索框搜索Docker。有多个Docker插件,使用Cloud Providers标题下的复选框选择Docker。
  • 点击直接安装
  • 插件将会自动下载并安装,安装完成后点击返回即可完成安装。

docker plugin

docker plugin

添加 docker agent

  • 在仪表板中,选择左侧的 系统管理
  • 在系统管理中,选择 系统设置
  • 在底部,有一个下拉菜单叫 增加一个云 ,从下拉列表中选择 Docker.
  • Docker Host URI 是 Jenkins 启动 agent 容器的位置,在本教程中,我们将使用我们前面定义好的 tcp://172.16.3.32:2375
  • 使用 Test Connection 来验证 Jenkins 是否可以与 Docker Daemon 通讯, 如果正常的话,你可以看到返回过来的 Docker version.

配置 Docker Agent Template

Docker Agent Template 是将会处理应用构建(比如自动化构建 Docker 镜像)的Container。

  • 单击 Docker Agent 模板…然后添加Docker模板。
  • 配置容器
    • 将 agent 的标签设置为 docker-agent。表示我们的 Jenkins 将使用具有该标签的容器来构建我们的应用程序。(类似于 k8s 中的标签选择器)
    • 在 Docker Image 选项里填写 benhall/dind-jenkins-agent:v2 。 镜像可以从 https://hub.docker.com/r/benhall/dind-jenkins-agent/ 获取。
  • 在容器设置下,在 Volumn 文本框中输入 /var/run/docker.sock:/var/run/docker.sock。这允许我们的构建容器与主机通信。
  • 在 Connect Method 选项里选择 Connect with SSH 选项。由于上一步填写的镜像基于 Jenkins SSH Slave 映像,这意味着默认的 Inject SSH 密钥将处理身份验证。
  • 单击保存。

Jenkins现在可以在需要时将Build Agent作为容器启动。

Configuration of docker agent

Configuration of docker agent

Create New Job

  • 选择新建一个 jobs
  • 填写 job 的名字为 Katacoda Jenkins Demo, 然后选择 自由项目,点击 OK.

New a job

New a job

  • 接下来在 job 配置页中,选择 “Restrict where this project can be run”, 这时需要在标签表达式(类似于标签选择器)填写我们配置 Docker Agent 时填写的标签: docker-agent, 如果一切正常的话,你会看到”Label is serviced by no nodes and 1 cloud”.

标签选择

标签选择

If you see the error message There’s no agent/cloud that matches this assignment. Did you mean ‘master’ instead of ‘docker-agent’?, then the Docker plugin and the Docker Agent has not been Enabled. Go back to configure the system options and enable both checkboxes.

docker info
docker build -t katacoda/jenkins-demo:${BUILD_NUMBER} .
docker tag katacoda/jenkins-demo:${BUILD_NUMBER} katacoda/jenkins-demo:latest
docker images

开始构建项目

现在我们可以回到我们刚刚新创建工作的主目录中,选择立即构建。一般情况下,初次构建过程时间比较长,因为要 pull 下来我们之前定义的Docker Agent的镜像,并且还要pull 下我们构建项目的 Docker镜像。

构建项目

构建项目

构建成功

构建成功

查看构建过程

查看构建过程

查看构建完成的镜像

这时候可以查看宿主机的docker镜像,打印结果如下

$ docker images
REPOSITORY                       TAG                 IMAGE ID            CREATED              SIZE
katacoda/jenkins-demo            latest              63b4e5d2500e        About a minute ago   5.81MB
postgres                         latest              67ebc8a2f066        3 months ago         237MB
redis                            latest              4e8db158f18d        3 months ago         83.4MB
golang                           latest              d0e7a411e3da        4 months ago         794MB
benhall/dind-jenkins-agent       v2                  8f582645af33        8 months ago         1.14GB
jenkins/jenkins                  2.112-alpine        481b49e06417        8 months ago         223MB
$ _

测试

$ docker run -d -p 80:80 katacoda/jenkins-demo:latest
c716310a068f3ad95ab19c5e5a977981e8f061dec7209b8a55c6f2840700ecce
$ curl localhost
<h1>This request was processed by host: c716310a068f</h1>

缺点

  • Jenkins 还没有达到完全自动化构建的目的
  • Jenkins 配置较为复杂,坑比较多

优点

  • 分布式的CICD解决方案
  • 强大的社区

常遇到的坑总结

  • jenkins启动一直显示 Jenkins正在启动,请稍后…

解决方法:

docker exec -it jenkins bash
cd /var/jenkins_home/updates/ #到jenkins的工作目录下
vim default.json
# 把 "connectionCheckUrl":"http://www.google.com/" 改为"connectionCheckUrl":"http://www.baidu.com/"
  • 最新版Jenkins首次安装一直停在向导界面问题

jenkins启动后一直停在那个获取网络界面。 你需要修改下配置文件,因为你所在网络被限制了。配置文件是$JENKINS_HOME/hudson.model.UpdateCenter.xml,默认内容如下:

<?xml version='1.0' encoding='UTF-8'?>
 <sites>
   <site>
    <id>default</id>
    <url>http://updates.jenkins-ci.org/update-center.json</url>
   </site>
</sites>

只需要将 url 改为 http://mirror.xmission.com/jenkins/updates/update-center.json 即可

  • 遇到问题有哪些 debug 方法
    • 在 Jenkins 的系统配置中的日志记录中查看
    • 在宿主机中,运行下面的命令
docker logs jenkins

总结

Jenkins 是 自动化运维和DevOps不可缺少的工具,它会使你的工作变得轻松,不在纠结环境配置等等,它也作为很多开源项目的项目管理工具,推荐使用!!!

接下来我将会介绍更加自动化构建项目的一种方案。