喵♂呜 的博客

一个刚毕业就当爹的程序猿 正在迷雾中寻找道路...

如何使用Docker搭建一套持续集成环境

毕业工作也有2年了 两年时间 在公司也搭建了一整套持续集成的环境 现在正好有时间 整理出来 使用Docker部署 希望对大家有帮助

本教程默认服务器IP为 192.168.0.2 下列所有相关涉及IP地方 都需要您手动替换为你所使用的环境

基础框架简介

  • 本套持续集成环境存在如下几个工具(之后可能会迭代新版本)
    • 容器环境(Docker)
    • 编排工具(Swarm)
    • 编排Web界面(Swirl)
    • 代码托管(Gogs)
    • 自动化构建/测试(Jenkins的Pipeline)
    • 构建WebHook/构建结果通知(这个Web服务我用了NodeJS主要是用来关联几个项目)

基础准备

安装 Docker

详见 Docker的安装使用以及常见问题和解决方案

安装 DockerCompose

详见 DockerCompose的安装与使用

初始化 Swarm 集群

详见 DockerSwarm的安装与使用

这里可以直接执行 docker swarm init 如果你只需要单个节点的话

安装 Swirl DockerSwarm管理界面

  • 安装启动(简化使用 这里用bolt存储)

  • 写入配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    cat > docker-compose.yml << EOF
    version: '3'

    services:
    swirl:
    image: cuigh/swirl
    environment:
    DB_TYPE: bolt
    DB_ADDRESS: /data/swirl
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - /yumc/config/swirl:/data/swirl
    ports:
    - 8001:8001
    deploy:
    placement:
    constraints: [node.role == manager]
    EOF
  • 部署服务(下列命令 二选一)

    • 单机部署
      1
      docker-compose up -d
    • 服务部署(推荐 重启Docker服务后会自动启动)
      1
      docker stack deploy -c docker-compose.yml swirl
  • 配置

搭建NFS用于存储环境相关数据 (PS: 单节点可以忽略 但是最好用数据卷)

详见 NFS安装与使用

新建编排 启动相关服务

手动单独部署 详见 在Docker上部署常用的服务

不过我们这里用编排直接部署

准备基础环境

  • SSH链接到服务器

  • 新建环境基础目录(随意 只要下面和这里匹配就行了)

    1
    sudo mkdir -p /yumc/volumes
  • 开启防火墙相关端口 这里以 CentOs7 为例 (当然你也可以只开80和443然后用Nginx反向代理出去)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    firewall-cmd --zone=public --add-port=80/tcp --permanent
    firewall-cmd --zone=public --add-port=443/tcp --permanent
    firewall-cmd --zone=public --add-port=3306/tcp --permanent
    firewall-cmd --zone=public --add-port=3000/tcp --permanent
    firewall-cmd --zone=public --add-port=8001/tcp --permanent
    firewall-cmd --zone=public --add-port=8080/tcp --permanent
    firewall-cmd --zone=public --add-port=8081/tcp --permanent
    firewall-cmd --zone=public --add-port=8082/tcp --permanent
    firewall-cmd --zone=public --add-port=8083/tcp --permanent
    firewall-cmd --reload

批量部署服务(二选一即可 推荐NFS存储 但是需要自行部署NFS服务)

单节点 数据存储在宿主机目录
  • 输入网址 http://192.168.0.2:8001 打开 Swirl
  • 依次点击集群 => 编排 => 新建
  • 输入名称 yumc (你随意 开心就好)
  • 内容复制以下部分 (注意 存储目录 /yumc/volumes 如果和上面不一样 需要全部替换成你自己的)
    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
    35
    36
    version: '3'

    services:
    # 数据库
    mysql:
    image: mysql:5.7
    environment:
    # 数据库 `root` 账户的密码
    MYSQL_ROOT_PASSWORD: root
    ports:
    - 3306:3306
    volumes:
    - /yumc/volumes/mysql:/var/lib/mysql
    # Gogs代码托管服务
    gogs:
    image: gogs/gogs
    ports:
    - 3000:3000
    volumes:
    - /yumc/volumes/gogs:/data
    # Jenkins构建工具
    jenkins:
    image: jenkins/jenkins:lts-alpine
    ports:
    - 8080:8080
    volumes:
    - /yumc/volumes/jenkins:/var/jenkins_home
    # 本地Maven镜像 Docker镜像和Registry
    nexus:
    image: sonatype/nexus3
    ports:
    - 8081:8081 #主端口
    - 8082:8082 #docker-hosted端口
    - 8083:8083 #registry端口
    volumes:
    - /yumc/volumes/nexus:/nexus-data
  • 点击提交
  • 回到编排页面 点击发布 然后等待服务启动
多节点 数据存储NFS数据卷 可以随意迁移 只要NFS存储不变
  • 输入网址 http://192.168.0.2:8001 打开 Swirl
  • 依次点击集群 => 编排 => 新建
  • 输入名称 yumc (你随意 开心就好)
  • 内容复制以下部分 (注意 需要自行配置NFS服务 并且授予对应的权限)
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    version: '3'

    services:
    # 数据库
    mysql:
    image: mysql:5.7
    environment:
    # 数据库 `root` 账户的密码
    MYSQL_ROOT_PASSWORD: root
    ports:
    - 3306:3306
    volumes:
    - mysql:/var/lib/mysql
    # Gogs代码托管服务
    gogs:
    image: gogs/gogs
    ports:
    - 3000:3000
    volumes:
    - gogs:/data
    # Jenkins构建工具
    jenkins:
    image: jenkins/jenkins:lts-alpine
    ports:
    - 8080:8080
    volumes:
    - jenkins:/var/jenkins_home
    # 本地Maven镜像 Docker镜像和Registry
    nexus:
    image: sonatype/nexus3
    ports:
    - 8081:8081 #主端口
    - 8082:8082 #docker-hosted端口
    - 8083:8083 #registry端口
    volumes:
    - nexus:/nexus-data
    volumes:
    mysql:
    driver_opts:
    type: nfs4
    o: addr=127.0.0.1,rw
    device: ":/yumc/app/nfs/docker/mysql"
    gogs:
    driver_opts:
    type: nfs4
    o: addr=127.0.0.1,rw
    device: ":/yumc/app/nfs/docker/gogs"
    jenkins:
    driver_opts:
    type: nfs4
    o: addr=127.0.0.1,rw
    device: ":/yumc/app/nfs/docker/jenkins"
    nexus:
    driver_opts:
    type: nfs4
    o: addr=127.0.0.1,rw
    device: ":/yumc/app/nfs/docker/nexus"
  • 点击提交
  • 回到编排页面 点击发布 然后等待服务启动

配置服务

新建相关数据库

参考 MySQL常用配置 创建 gogs 数据库 和 一个 gogs 的账户 同时授予 gogs 数据库权限

简易创建教程
  • 输入网址 http://192.168.0.2:8001 打开 Swirl
  • 依次点击集群 => 编排
  • 点击 yumc_mysql 绿色的框框 进入服务页面
  • 滑到底 点击那个Tasks里面的第一个蓝色链接 进入任务页面
  • 点击 Container ID 边上的一串 Hash 值 (PS: 单机器集群可以直接进入)
  • 选择最后一个执行的Tab 点击连接
  • 简易教程进入容器终端 执行下列命令
    1
    2
    3
    4
    5
    mysql -h localhost -u root -p
    Enter Password:
    > CREATE DATABASE gogs;
    > CREATE USER 'gogs'@'%' IDENTIFIED BY 'Yumc2018Gogs@';
    > GRANT ALL ON gogs.* TO 'gogs'@'%';

配置 代码托管平台 Gogs

  • 打开 http://192.168.0.2:3000
  • 配置相关参数
  • 数据库地址填入 mysql:3306 (因为处于同一个编排下 所以 hosts 会自动写入)
  • 初始化之后可以直接进入

配置 构建工具 Jenkins

  • 输入网址 http://192.168.0.2:8001 打开 Swirl
  • 依次点击集群 => 编排
  • 点击 yumc_jenkins 绿色的框框 进入服务页面
  • 点击 日志Tab 选择 Stderr 找到临时密码
  • 输入网址 http://192.168.0.2:8080 打开 Jenkins
  • 进入后 注册管理账户 一路下一步即可

配置 Nexus 镜像仓库

  • 输入网址 http://192.168.0.2:8081 打开 Nexus
  • 输入默认的账号 admin 密码 admin123 (登录之后推荐修改默认密码或新建账号)
配置 Maven 仓库
配置 Docker 仓库
  • 进入 http://192.168.0.2:8081/#admin/repository/repositories
  • 创建 proxy 仓库 用于代理官方仓库
    • 依次点击 Create repository => docker (proxy)
    • 填写参数
      • Name: docker-hosted
      • Proxy区域
        • Remote storage: Location of the remote repository being proxied
          • 填写 https://registry-1.docker.io
        • Docker Index:
          • 选择 Use Docker Hub
      • Storage区域

  • 创建 hosted 仓库 用于存储内部的镜像
    • 依次点击 Create repository => docker (hosted)
    • 填写参数
      • Name: docker-hosted
      • HTTP: Create an HTTP connector at specified port. Normally used if the server is behind a secure proxy.
        • 勾选 并且填上 8082
  • 创建 groups 仓库 用于聚合多个仓库(proxy hosted)
    • 依次点击 Create repository => docker (group)
    • 填写参数
      • Name: docker-group
      • Repository Connectors区域
        • HTTP: Create an HTTP connector at specified port. Normally used if the server is behind a secure proxy.
          • 勾选 并且填上 8083
      • Group区域
        • Member repositories: Select and order the repositories that are part of this group
          • 选择 docker-hosted docker.io(把docker-hosted放在第一位可以加快内部镜像拉取速度)
配置 Npm 仓库(可选 如果你们用到了 NodeJS)

配置监控

新建 GrafanaPrometheus 以及相关的 exporter 的编排

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
version: '3'

services:
prometheus:
image: prom/prometheus
ports:
- 9090:9090
volumes:
- /yumc/config/prometheus:/etc/prometheus
- prometheus:/prometheus
grafana:
image: grafana/grafana
ports:
- 3300:3000
volumes:
- grafana:/var/lib/grafana
environment:
GF_SERVER_ROOT_URL: https://grafana.yumc.pw
GF_SECURITY_ADMIN_PASSWORD: Jtb2hwwfor
node-exporter:
image: prom/node-exporter
ports:
- target: 9100
published: 9100
protocol: tcp
mode: host
volumes:
- /proc:/host/proc
- /sys:/host/sys
- /:/rootfs
deploy:
mode: global
cadvisor:
image: google/cadvisor
ports:
- target: 8080
published: 9101
protocol: tcp
mode: host
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
deploy:
mode: global
resources:
limits:
cpus: '0.2'
memory: 256M
reservations:
cpus: '0.1'
memory: 128M
volumes:
grafana:
driver_opts:
type: nfs4
o: addr=127.0.0.1,rw
device: ":/yumc/app/nfs/docker/grafana"
prometheus:
driver_opts:
type: nfs4
o: addr=127.0.0.1,rw
device: ":/yumc/app/nfs/docker/prometheus"

新建 Prometheus 的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat >/yumc/config/prometheus/prometheus.yml<<EOF
global:
scrape_interval: 10s
evaluation_interval: 10s

scrape_configs:
- job_name: prometheus
static_configs:
- targets: ['localhost:9090']
labels:
instance: prometheus

- job_name: linux
static_configs:
- targets: ['192.168.0.2:9100']

- job_name: docker
static_configs:
- targets: ['192.168.0.2:9101']
EOF

启动编排

未完待续

欢迎关注我的其它发布渠道