Lain's Blog

基于Jenkins、Gitlab构建持续集成、持续交付的Docker容器集群

概述

基于Jenkins、Gitlab构建持续集成、持续交付的Docker容器集群。

准备

环境

  • Linux系统(以ubuntu示例)
  • Docker运行环境
  • docker-compose编排工具

安装Docker

安装Docker执行以下命令:

1
curl -fsSL https://get.docker.io | bash

注:升级内核

安装docker-compose

默认的[官方文档][]安装命令如下:

1
curl -L https://github.com/docker/compose/releases/download/1.6.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

搭建基础服务

CI、CD涉及的基础服务有:

  1. 代码仓库(以Gitlab示例)
  2. 镜像仓库(以搭建私有镜像仓库示例)
  3. 代码构建(以Jenkins示例)
  4. 容器集群(以swarm示例)

代码仓库(构建Gitlab服务)

GitLab是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目;类似于Github。

选一台主机以docker化的方式来搭建Gitlab服务。(已有私有Gitlab仓库或使用Github,可跳过此步骤)

我们选择Docker Hub上的sameersbn/gitlab镜像来快速构建Gitlab服务。
根据sameersbn/docker-gitlab给出的文档,我们需要启动三个容器组件.

Docker cli启动方式

  • 启动postgresql容器(可使用外部数据、也可使用mqsql存储,具体参见文档)
1
2
3
4
5
6
7
docker run --name gitlab-postgresql -d \
--env 'DB_NAME=gitlabhq_production' \
--env 'DB_USER=gitlab' \
--env 'DB_PASS=password' \
--env 'DB_EXTENSION=pg_trgm' \
--volume /srv/docker/gitlab/postgresql:/var/lib/postgresql \
sameersbn/postgresql:9.5-3
  • 启动redis容器

    1
    2
    3
    docker run --name gitlab-redis -d \
    --volume /srv/docker/gitlab/redis:/var/lib/redis \
    sameersbn/redis:latest
  • 启动gitlab容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    docker run --name gitlab -d \
    --link gitlab-postgresql:postgresql --link gitlab-redis:redisio \
    --publish 10022:22 --publish 10080:80 \
    --env 'GITLAB_PORT=10080' \
    --env 'GITLAB_SSH_PORT=10022' \
    --env 'GITLAB_SECR
    ETS_DB_KEY_BASE=long-and-random-alpha-numeric-string' \
    --env 'GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alpha-numeric-string' \
    --env 'GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alpha-numeric-string' \
    --volume /srv/docker/gitlab/gitlab:/home/git/data \
    sameersbn/gitlab:latest

docker-compose启动方式

通常处理复杂容器之间的配置依赖关系可以使用docker-compose工具来管理,用法参见docker-compose文档

使用docker-compose的启动方式,需要docker-compose.yml文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
gitlab:
image: sameersbn/gitlab
ports:
- "10022:22"
- "10080:80"
links:
- gitlab-redis:redisio
- gitlab-postgresql:postgresql
environment:
- GITLAB_PORT=80
- GITLAB_SSH_PORT=22
- GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alpha-numeric-string
- GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alpha-numeric-string
- GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alpha-numeric-string
volumes:
- /srv/docker/gitlab/gitlab:/home/git/data
restart: always
gitlab-redis:
image: sameersbn/redis
volumes:
- /srv/docker/gitlab/redis:/var/lib/redis
restart: always
gitlab-postgresql:
image: sameersbn/postgresql:9.5-3
environment:
- DB_NAME=gitlabhq_production
- DB_USER=gitlab
- DB_PASS=password
- DB_EXTENSION=pg_trgm
volumes:
- /srv/docker/gitlab/postgresql:/var/lib/postgresql
restart: always

执行以下命令,构建gitlab服务

1
docker-compose up -d

测试

执行docker ps命令查看:

docker ps 结果显示

访问\:10080,查看Gitlab网页是否正常,并设置root账初始密码。

镜像仓库(构建Docker私有仓库)

镜像管理是Docker容器的核心,Docker官方在Github上有一个项目docker-registry, 专门用于自建Docker的私有镜像库。

在CI、CD中,需要一个Docker镜像仓库来存放每次构建的镜像(使用公有镜像仓库如Docker Hub可以自行跳过)。
从镜像的安全、可靠、访问速度等因素考虑,搭建一个私有的镜像仓库,对企业级开发和实践是很有必要的。

Docker cli构建方式

最简便的创建方式:

1
2
docker run -d --restart=always --name registry \
-v /mnt/docker/registry:/var/lib/registry -p 5000:5000 registry:2

docker-compose构建方式

编写docker-compose.yml文件,内容如下:

1
2
3
4
5
6
7
registry:
image: registry:2
ports:
- "5000:5000"
volumes:
- /mnt/docker/registry:/var/lib/registry
restart: always

执行docker-compose up -d命令

测试

  • 执行docker ps 可查看registry容器运行状态。
  • 测试推送/拉取
    1
    2
    docker pull 镜像仓库ip:端口/<命名空间>/项目名称 # 拉取镜像
    docker push 镜像仓库ip:端口/<命名空间>/项目名称 # 推送镜像

注:docker私有镜像仓库 拉取/推送 失败,提示不能使用http连接。解决方法:
1、设置https访问,参见企业级的Docker Registry搭建
2、在docker启动参数里添加–insecure-registry \:\,然后重启docker。

镜像构建(搭建Jenkins服务)

Jenkins是基于Java开发的一种开源持续集成工具,监控并触发持续重复的工作,具有开源,支持多平台和插件扩展,安装简单,界面化管理等特点。Jenkins使用job来描述每一步工作,节点是用来执行项目的环境。Master节点是Jenkins job的默认执行环境,也是Jenkins应用本身的安装环境
使用官方的Jenkins镜像来构建我们的Jenkins服务。

Docker cli构建方式

执行以下命令:

1
2
3
docker run docker run -d -p 8080:8080 \
--name jenkins --restart=always -v /mnt/jenkins_home:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock jayqqaa12/jenkins

参数说明:

1
2
-v /mnt/jenkins_home:/var/jenkins_home # 映射volumes到本地存储
-v /var/run/docker.sock:/var/run/docker.sock # 映射主机的docker到容器里面 这样在容器里面就可以使用主机安装的 docker 了

docker-compose构建方式

编写docker-compose.yml文件,内容如下:

1
2
3
4
5
6
7
8
jenkins:
image: jayqqaa12/jenkins
ports:
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /mnt/jenkins_home:/var/jenkins_home
restart: always

执行docker-compose up -d命令

测试

  • 执行docker ps 查看jenkins容器运行情况
  • 在浏览器中,打开http://\:8080,进入jenkins,默认用户/密码(admin/admin)

容器集群(构建Docker Swarm集群)

容器集群管理工具主要有k8s、mesos、swarm,以及从Docker1.12版本出现的swarmkit。这里以swarm示例容器集群的简单操作。

Swarm是Docker官方发布的一套较为简单的容器集群管理工具,它将一群Docker宿主机变成一个单一的虚拟主机。Swarm使用标准的Docker API接口,因此能可以很方便地和docker的标准API进行集成。

下面,使用Docker-Swarm来创建一个docker容器集群

1
2
3
4
5
6
7
8
9
10
#创建一个swarm集群 ,会返回一个token来替换下面命令的<token>
docker run --rm swarm create
# 创建集群的管理容器swarm 来管理所有节点
docker run -d --name swarm-manage --restart=always -p \
2376:2375 swarm manage token://<token>
#添加节点到swarm集群中
docker run -d --restart=always --name swarm-agent swarm \
join --addr=当前服务器的ip:2375 token://<token>
1
2
#查看集群的节点信息
docker -H 管理节点的ip:2376 info

查看当前集群信息,只有一个节点:

swarm集群信息

1
2
docker -H 管理节点的ip:2376 run xxx #运行容器
docker -H 管理节点的ip:2376 ps xxx #查看集群容器运行情况

以上是使用swarm集群运行、查看容器,更多swarm集群操作详见swarm文档

注:节点发现无法连接,则需要在Docker daemon添加启动参数:

1
2
3
--insecure-registry <镜像仓库host>:<port> # 设置仓库为http访问
-H unix:///var/run/docker.sock -H 0.0.0.0:2375 #打开节点对外通信接口
--label label_name=swarm-node1 # 设置一下label 方便区分

Demo: 基于Docker构建持续集成(CI)、持续部署(CD)的Flask项目

以上,我们搭建了基于Docker的CI、CD的基础服务,下面我们创建一个Flask项目的Demo来测试下:

  1. 在gitlab创建python-hello-world项目仓库
  2. clone项目,本地开发
  3. 配置jenkins
  4. 触发构建

gitlab上新建项目

在gitlab创建python-hello-world项目仓库。

enter description here

本地开发

编写Flask应用

创建app.py

1
2
3
4
5
6
7
8
9
10
11
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return "Hello World! <br/> version: v1 author: lain"
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000)

创建requirements.txt:

1
flask

编写Dockerfile

创建Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
From python:2.7
MAINTAINER lain
ADD . /app
WORKDIR ./app
RUN pip install -r requirements.txt
EXPOSE 5000
CMD ["python", "/app/hello.py"]

创建构建部署脚本

创建build_deploy.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash
#build in jenkins
# docker私有仓库的地址
REG_URL=xxxx
# swarm集群manage节点的地址
SWARM_MANAGE_URL=xx:2376
#根据时间生成tag
TAG=$REG_URL/$JOB_NAME:`date +%y%m%d-%H-%M`
#使用项目目录下的Dockerfile文件打包
docker build -t $TAG $WORKSPACE/.
docker push $TAG
docker rmi $TAG
# 检测是否有运行的版本,有就删了
if docker -H $SWARM_MANAGE_URL ps -a| grep -i $JOB_NAME; then
docker -H $SWARM_MANAGE_URL rm -f $JOB_NAME
fi
#在swarm集群运行
docker -H $SWARM_MANAGE_URL run -d -p 80:5000 --name $JOB_NAME $TAG

配置Jenkins

在Jenkins上创建一个python-hello-world项目,选择自由风格即可:

enter description here

设置git:

enter description here

设置构建触发器,这里设置每分钟拉取一次,也可设置gitlab hook:

enter description here

设置构建需要执行的脚本,这里设置成build_deploy.sh:

enter description here

触发CI、CD

推送到代码到gitlab的master分支,然后查看jenkins console,就可以查看到构建集成和部署的过程。

enter description here

访问测试

访问浏览器,已经部署到swarm集群(关于集群的负载均衡,请自行查阅。)

enter description here

更新代码版本,并推送到代码仓库gilab:

1
2
3
4
5
6
7
8
9
10
11
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return "Hello World! <br/> version: v2 author: lain"
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000)

等待2分钟,可以在jenkins查看到新的构建是否成功,访问浏览器:

enter description here

容器监控

关于采集容器运行信息数据、查看容器运行情况、日志等,通过命令行的方式是很不方便的,因此我们需要搭建一个容器监控平台,开源的工具有
如何管理容器 查看容器运行情况 日志等都不太方便 我们需要搭建一个监控平台cAdvisor等。(这里不再叙述)

扫二维码
扫一扫,用手机访问本站

扫一扫,用手机访问本站