4 Docker 结合 Jenkins 构建持续集成环境

4.1 持续集成是什么

02 Docker 实现CICD%26Docker 高级部分 - 图1

持续:完成一个新功能就向下一一个环节交付,不断发现问题,解决问题。

集成:研发人员提交新代码到主干,进行构建、部署、测试,不断做集成,修正集成结果。

部署:将项目发布到测试环境、预生产环境或生产环境。

交付:将最终产品发布到预生产环境或生产环境,给用户使用。

  • 持续集成 (Continuous Integration) :代码合并、构建、部署、测试都在一-起, 不断地执行这个过程,并对结果反馈。
  • 持续交付 (Continuous Delivery) :将最终产品发布到生产环境,给用户使用。
  • 持续部署 (Continuous Deployment) :将新需求部署到生产环境。

4.2 持续集成相关工具

Jenkins:一个开源的持续集成工具,提供软件版本发布、自动测试等一系 列流程及丰富的插件。

Maven:一个自动化构建工具,通过-段描述来管理项目的构建,比如编译、打包等逻辑流程。

SVN/Git:源代码版本管理工具。

Docker:容器化技术;打包项目环境与快速部署。

4.3 Docker + Jenkins + Maven + SVN搭建持续集成环境

Reference:https://www.cnblogs.com/xiangsikai/p/10057087.html

4.3.1 发布流程设计

:::color1 Java 环境 CI

:::

02 Docker 实现CICD%26Docker 高级部分 - 图2

:::color1 PHP 环境 CI

:::

02 Docker 实现CICD%26Docker 高级部分 - 图3

:::color1 发布流程设计

:::

02 Docker 实现CICD%26Docker 高级部分 - 图4

:::color1 环境说明

:::

服务器 IP地址
Jenkins 10.0.0.30
测试环境 10.0.0.31
生产环境 10.0.0.32
  • 操作系统:Ubuntu16.04_x64 & CentOS 7.9.2009_x64
  • Maven 3.5+
  • Tomcat 8+
  • JDK 1.8+
  • Jenkins 2.7+
  • Docker CE 17.06+

4.3.2 SVN安装配置及简单使用

  1. # 修改主机名
  2. $ hostnamectl set-hostname jenkins-svn-ssh
  3. # 安装SVN软件
  4. $ apt-get install subversion
  5. $ mkdir -pv /home/svn
  6. # 创建SVN仓库
  7. $ svnadmin create /home/svn/repos
  8. # 修改SVN配置文件
  9. $ vi /home/svn/repos/conf/svnserve.conf
  10. # 打开以下功能
  11. anon-access = none
  12. auth-access = write
  13. password-db = passwd
  14. authz-db = authz
  15. # 添加SVN登录账号
  16. $ vi /home/svn/repos/conf/passwd
  17. [users]
  18. test = 123456
  19. # SVN账号的权限
  20. $ vi /home/svn/repos/conf/authz
  21. [repos:/]
  22. test = rw
  23. # 启动SVN服务
  24. $ svnserve -d -r /home/svn
  25. # 查看SVN进程
  26. $ ps -ef | grep svn
  27. root 100712 1 0 01:46 ? 00:00:00 svnserve -d -r /home/svn
  28. # 仓库地址: svn://10.0.0.30/repos

Download SVN Client:https://tortoisesvn.net/

Download Reference:https://tortoisesvn.net/downloads.html

  • 打开TortoiseSVN Repository Browser软件,填入相应的SVN URL

02 Docker 实现CICD%26Docker 高级部分 - 图5

  • 在 Desktop 桌面中右键找到”SVN CheckOut”,将远程SVN的 Repo 拉到本地

02 Docker 实现CICD%26Docker 高级部分 - 图6

  • 在 CheckOut 的目录下创建 index.html 默认页面
  1. <h1>Hello world</h1>

02 Docker 实现CICD%26Docker 高级部分 - 图7

02 Docker 实现CICD%26Docker 高级部分 - 图8

4.3.3 Docker镜像仓库搭建

  1. $ docker run -d \
  2. -v /opt/registry:/var/lib/registry \
  3. -p 5000:5000 \
  4. --restart=always \
  5. --name registry \
  6. registry
  7. # 查看资源,映射宿主机端口到容器端口
  8. $ docker ps -l
  9. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  10. e84dff8aa72b registry "/entrypoint.sh /etc…" 51 seconds ago Up 49 seconds 0.0.0.0:5000->5000/tcp registry

在部署节点配置Docker可信任私有仓库:

  1. # vim /etc/docker/daemon.json
  2. {
  3. "registry-mirrors": ["https://po13h3y1.mirror.aliyuncs.com","http://hub-mirror.c.163.com","https://mirror.ccs.tencentyun.com","http://f1361db2.m.daocloud.io"],
  4. "exec-opts": ["native.cgroupdriver=systemd"],
  5. "log-driver": "json-file",
  6. "log-opts": {
  7. "max-size": "100m"
  8. },
  9. "storage-driver": "overlay2",
  10. "insecure-registries": ["10.0.0.30:5000"]
  11. }
  12. # 所有节点设置可信任仓库
  13. $ systemctl daemon-reload && systemctl restart docker
  14. # 查看当前仓库上传的镜像
  15. $ curl http://10.0.0.30:5000/v2/_catalog
  16. {"repositories":[]}
  17. # 查看指定镜像的Tags版本
  18. $ curl http://10.0.0.30:5000/v2/lnmp-nginx/tags/list
  19. {"name":"lnmp-nginx","tags":["base"]}
  1. # 解压包,进入nginx目录
  2. unzip Dockerfile-lnmp.zip;cd Dockerfile-lnmp/nginx/
  3. # 需要添加镜像Yum源(vim Dockerfile)
  4. RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-6.10.repo
  5. # 构建nginx镜像容器
  6. docker build -t 10.0.0.30:5000/lnmp-nginx:base .
  7. ####################################################################################################
  8. # 进入php目录
  9. cd ../php/
  10. # 需要添加镜像Yum源(vim Dockerfile)
  11. RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-6.10.repo
  12. # 构建php镜像如期
  13. docker build -t 10.0.0.30:5000/lnmp-php:base .

上传基础镜像到私有仓库:

参考一键部署LNMP网站平台的配置:

01 Docker 进阶 & Kubernetes 入门

  1. # Docker Compose 存放在Git Hub,不太稳定。
  2. # 可以也通过执行下面的命令,高速安装Docker Compose。
  3. curl -L https://get.daocloud.io/docker/compose/releases/download/v2.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
  4. chmod +x /usr/local/bin/docker-compose
  5. # 所有节点安装
  6. # 构建镜像
  7. docker build -t 10.0.0.30:5000/lnmp-nginx:base .
  8. docker build -t 10.0.0.30:5000/lnmp-php:base .
  9. # 注:地址IP需要根据环境修改,确认执行完毕,无误。
  10. # 推送镜像到私有仓库
  11. docker push 10.0.0.30:5000/lnmp-nginx:base
  12. docker push 10.0.0.30:5000/lnmp-php:base
  13. # 报错处理:https://www.cnblogs.com/lkun/p/7990466.html

4.3.4 部署节点安装Docker与Docker- Compose及配置普通用户 sudo

注:保证所有节点都提前安装好Docker应用
  1. 安装Docker

Install Reference:https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu

  1. #!/bin/bash
  2. #Description:全系列系统安装 docker harbor镜像仓库
  3. HARBOR_VERSION=2.6.0
  4. HARBOR_BASE=/apps
  5. HARBOR_NAME=harbor.wang.org
  6. DOCKER_VERSION="20.10.10"
  7. #DOCKER_VERSION="19.03.14"
  8. DOCKER_COMPOSE_VERSION=2.6.1
  9. #DOCKER_COMPOSE_VERSION=1.29.2
  10. DOCKER_COMPOSE_FILE=docker-compose-Linux-x86_64
  11. #HARBOR_NAME=`hostname -I|awk '{print $1}'`
  12. HARBOR_ADMIN_PASSWORD=123456
  13. HARBOR_IP=`hostname -I|awk '{print $1}'`
  14. COLOR_SUCCESS="echo -e \\033[1;32m"
  15. COLOR_FAILURE="echo -e \\033[1;31m"
  16. END="\033[m"
  17. . /etc/os-release
  18. UBUNTU_DOCKER_VERSION="5:${DOCKER_VERSION}~3-0~${ID}-${UBUNTU_CODENAME}"
  19. color () {
  20. RES_COL=60
  21. MOVE_TO_COL="echo -en \\033[${RES_COL}G"
  22. SETCOLOR_SUCCESS="echo -en \\033[1;32m"
  23. SETCOLOR_FAILURE="echo -en \\033[1;31m"
  24. SETCOLOR_WARNING="echo -en \\033[1;33m"
  25. SETCOLOR_NORMAL="echo -en \E[0m"
  26. echo -n "$1" && $MOVE_TO_COL
  27. echo -n "["
  28. if [ $2 = "success" -o $2 = "0" ] ;then
  29. ${SETCOLOR_SUCCESS}
  30. echo -n $" OK "
  31. elif [ $2 = "failure" -o $2 = "1" ] ;then
  32. ${SETCOLOR_FAILURE}
  33. echo -n $"FAILED"
  34. else
  35. ${SETCOLOR_WARNING}
  36. echo -n $"WARNING"
  37. fi
  38. ${SETCOLOR_NORMAL}
  39. echo -n "]"
  40. echo
  41. }
  42. install_docker(){
  43. if [ $ID = "centos" -o $ID = "rocky" ];then
  44. if [ $VERSION_ID = "7" ];then
  45. cat > /etc/yum.repos.d/docker.repo <<EOF
  46. [docker]
  47. name=docker
  48. gpgcheck=0
  49. #baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/
  50. baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/x86_64/stable/
  51. EOF
  52. else
  53. cat > /etc/yum.repos.d/docker.repo <<EOF
  54. [docker]
  55. name=docker
  56. gpgcheck=0
  57. #baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/
  58. baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/8/x86_64/stable/
  59. EOF
  60. fi
  61. yum clean all
  62. ${COLOR_FAILURE} "Docker有以下版本"${END}
  63. yum list docker-ce --showduplicates
  64. ${COLOR_FAILURE}"5秒后即将安装: docker-"${DOCKER_VERSION}" 版本....."${END}
  65. ${COLOR_FAILURE}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
  66. sleep 5
  67. yum -y install docker-ce-$DOCKER_VERSION docker-ce-cli-$DOCKER_VERSION \
  68. || { color "Base,Extras的yum源失败,请检查yum源配置" 1;exit; }
  69. else
  70. dpkg -s docker-ce &> /dev/null && $COLOR"Docker已安装,退出" 1 && exit
  71. apt update || { color "更新包索引失败" 1 ; exit 1; }
  72. apt -y install apt-transport-https ca-certificates curl software-properties-common || \
  73. { color "安装相关包失败" 1 ; exit 2; }
  74. curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
  75. add-apt-repository "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
  76. apt update
  77. ${COLOR_FAILURE} "Docker有以下版本"${END}
  78. apt-cache madison docker-ce
  79. ${COLOR_FAILURE}"5秒后即将安装: docker-"${UBUNTU_DOCKER_VERSION}" 版本....."${END}
  80. ${COLOR_FAILURE}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
  81. sleep 5
  82. apt -y install docker-ce=${UBUNTU_DOCKER_VERSION} docker-ce-cli=${UBUNTU_DOCKER_VERSION}
  83. fi
  84. if [ $? -eq 0 ];then
  85. color "安装软件包成功" 0
  86. else
  87. color "安装软件包失败,请检查网络配置" 1
  88. exit
  89. fi
  90. mkdir -p /etc/docker
  91. tee /etc/docker/daemon.json <<-'EOF'
  92. {
  93. "registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"],
  94. "insecure-registries": ["harbor.wang.org"]
  95. }
  96. EOF
  97. systemctl daemon-reload
  98. systemctl enable docker
  99. systemctl restart docker
  100. docker version && color "Docker 安装成功" 0 || color "Docker 安装失败" 1
  101. echo 'alias rmi="docker images -qa|xargs docker rmi -f"' >> ~/.bashrc
  102. echo 'alias rmc="docker ps -qa|xargs docker rm -f"' >> ~/.bashrc
  103. }
  104. install_docker_compose(){
  105. if [ $ID = "centos" -o $ID = "rocky" ];then
  106. ${COLOR_SUCCESS}"开始安装 Docker compose....."${END}
  107. sleep 1
  108. if [ ! -e ${DOCKER_COMPOSE_FILE} ];then
  109. #curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/${DOCKER_COMPOSE_FILE} -o /usr/bin/docker-compose
  110. curl -L https://get.daocloud.io/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) -o /usr/bin/docker-compose
  111. else
  112. mv ${DOCKER_COMPOSE_FILE} /usr/bin/docker-compose
  113. fi
  114. chmod +x /usr/bin/docker-compose
  115. else
  116. apt -y install docker-compose
  117. fi
  118. if docker-compose --version ;then
  119. ${COLOR_SUCCESS}"Docker Compose 安装完成"${END}
  120. else
  121. ${COLOR_FAILURE}"Docker compose 安装失败"${END}
  122. exit
  123. fi
  124. }
  125. install_harbor(){
  126. ${COLOR_SUCCESS}"开始安装 Harbor....."${END}
  127. sleep 1
  128. if [ ! -e harbor-offline-installer-v${HARBOR_VERSION}.tgz ] ;then
  129. wget https://github.com/goharbor/harbor/releases/download/v${HARBOR_VERSION}/harbor-offline-installer-v${HARBOR_VERSION}.tgz || ${COLOR_FAILURE} "下载失败!" ${END}
  130. fi
  131. [ -d ${HARBOR_BASE} ] || mkdir ${HARBOR_BASE}
  132. tar xvf harbor-offline-installer-v${HARBOR_VERSION}.tgz -C ${HARBOR_BASE}
  133. cd ${HARBOR_BASE}/harbor
  134. cp harbor.yml.tmpl harbor.yml
  135. sed -ri "/^hostname/s/reg.mydomain.com/${HARBOR_NAME}/" harbor.yml
  136. sed -ri "/^https/s/(https:)/#\1/" harbor.yml
  137. sed -ri "s/(port: 443)/#\1/" harbor.yml
  138. sed -ri "/certificate:/s/(.*)/#\1/" harbor.yml
  139. sed -ri "/private_key:/s/(.*)/#\1/" harbor.yml
  140. sed -ri "s/Harbor12345/${HARBOR_ADMIN_PASSWORD}/" harbor.yml
  141. sed -i 's#^data_volume: /data#data_volume: /data/harbor#' harbor.yml
  142. #mkdir -p /data/harbor
  143. ${HARBOR_BASE}/harbor/install.sh && ${COLOR_SUCCESS}"Harbor 安装完成"${END} || ${COLOR_FAILURE}"Harbor 安装失败"${END}
  144. cat > /lib/systemd/system/harbor.service <<EOF
  145. [Unit]
  146. Description=Harbor
  147. After=docker.service systemd-networkd.service systemd-resolved.service
  148. Requires=docker.service
  149. Documentation=http://github.com/vmware/harbor
  150. [Service]
  151. Type=simple
  152. Restart=on-failure
  153. RestartSec=5
  154. ExecStart=/usr/bin/docker-compose -f ${HARBOR_BASE}/harbor/docker-compose.yml up
  155. ExecStop=/usr/bin/docker-compose -f ${HARBOR_BASE}/harbor/docker-compose.yml down
  156. [Install]
  157. WantedBy=multi-user.target
  158. EOF
  159. systemctl daemon-reload
  160. systemctl enable harbor &>/dev/null || ${COLOR}"Harbor已配置为开机自动启动"${END}
  161. if [ $? -eq 0 ];then
  162. echo
  163. color "Harbor安装完成!" 0
  164. echo "-------------------------------------------------------------------"
  165. echo -e "请访问链接: \E[32;1mhttp://${HARBOR_IP}/\E[0m"
  166. echo -e "用户和密码: \E[32;1madmin/${HARBOR_ADMIN_PASSWORD}\E[0m"
  167. else
  168. color "Harbor安装失败!" 1
  169. exit
  170. fi
  171. echo "$HARBOR_IP $HARBOR_NAME" >> /etc/hosts
  172. }
  173. docker info &> /dev/null && ${COLOR_FAILURE}"Docker已安装"${END} || install_docker
  174. docker-compose --version &> /dev/null && ${COLOR_FAILURE}"Docker Compose已安装"${END} || install_docker_compose
  175. # install_harbor
  1. 安装Docker Compose
  1. # curl -L https://github.com/docker/compose/releases/download/1.14.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
  2. # chmod +x /usr/local/bin/docker-compose
  3. curl -L https://get.daocloud.io/docker/compose/releases/download/v2.14.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
  4. chmod +x /usr/local/bin/docker-compose
  1. 赋予用户sudo权限
  1. $ vi /etc/sudoers
  2. user ALL= (ALL) NOPASSWD:ALL

4.3.5 Jenkins安装

将二进制包上传到服务器并解压到工作目录,用于让Jenkins容器挂载使用。

  1. # JDK Download:https://lupf.cn/articles/2022/02/19/1645283667689.html
  2. # Maven Download:https://dlcdn.apache.org/maven/maven-3/3.5.4/binaries/
  3. # wget https://dlcdn.apache.org/maven/maven-3/3.5.4/binaries/apache-maven-3.5.4-bin.tar.gz --no-check-certificate
  4. tar -zxvf jdk-8u45-linux-x64.tar.gz
  5. mv jdk1.8.0_45/ /usr/local/jdk
  6. tar apache-maven-3.5.4-bin.tar.gz
  7. mv apache-maven-3.5.4/ /usr/local/maven

修改Maven源:

  1. # docker pull jenkins/jenkins:lts
  2. docker pull jenkins/jenkins:2.375.1-lts
  3. docker run -d --name jenkins -p 80:8080 -p 50000:50000 -u root \
  4. -v /opt/jenkins_home:/var/jenkins_home \
  5. -v /var/run/docker.sock:/var/run/docker.sock \
  6. -v /usr/bin/docker:/usr/bin/docker \
  7. -v /usr/local/maven:/usr/local/maven \
  8. -v /usr/local/jdk:/usr/local/jdk \
  9. -v /etc/localtime:/etc/localtime \
  10. --restart=always \
  11. --name jenkins jenkins/jenkins:2.375.1-lts
  12. # 查看Jenkins日志
  13. $ docker logs -f jenkins
  14. # 查看Jenkins的进程信息
  15. $ docker ps -l
  16. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  17. 3a70a5fa86cc jenkins/jenkins:2.375.1-lts "/usr/bin/tini -- /u…" 50 seconds ago Up 49 seconds 0.0.0.0:50000->50000/tcp, 0.0.0.0:80->8080/tcp jenkins

访问地址:http://IP

02 Docker 实现CICD%26Docker 高级部分 - 图9

:::warning Jenkins 是类似于 Docker in Docker 的模式

:::

  1. # 获取Jenkins的管理员密码
  2. $ docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword
  3. e28b88f6c04b468aa8f08300a5d0cc86

Jenkins 使用安装推荐的插件

02 Docker 实现CICD%26Docker 高级部分 - 图10


  1. # 安装包下载:
  2. http://mirrors.jenkins.io/war-stable/
  3. http://maven.apache.org/download.cgi
  4. http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
  5. # 配置JDK和Maven环境变量:
  6. $ tar zxvf jdk-8u45-linux-x64.tar.gz
  7. $ mv jdk1.8.0_45 /usr/locol/jdk1.8
  8. $ tar apache-maven-3.5.0-bin.tar.gz
  9. $ mv apache-maven-3.5.0 /usr/local/maven3.5
  10. $ vi /etc/profile
  11. JAVA_HOME=/usr/local/jdk1.8
  12. CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
  13. MAVEN_HOME=/usr/local/maven3.5
  14. PATH=$JAVA_HOME/bin:$MAVEN HOME/bin:$PATH
  15. export JAVA_HOME CLASSPATH MAVEN HOME PATH
  16. $ tar zxvf apache-tomcat-8.0.46.tar.gz
  17. $ cd apache-tomcat-8.0.46/webapps
  18. $ rm -rf./*
  19. $ unzip /root/jenkins.war -d ROOT
  20. # Jenkins 启动
  21. $ .. /bin/startup.sh

4.3.6 Jenkins基本配置

:::color1 系统配置

:::

02 Docker 实现CICD%26Docker 高级部分 - 图11

添加 SSH 远程主机的配置

02 Docker 实现CICD%26Docker 高级部分 - 图12

02 Docker 实现CICD%26Docker 高级部分 - 图13

Publish over SSH 配置( 生产环境的主机项目代码传到部署节点。(保存) )

02 Docker 实现CICD%26Docker 高级部分 - 图14

测试连接( 需要在远程主机中创建相应工作目录 )

02 Docker 实现CICD%26Docker 高级部分 - 图15

保存相应的配置即可!

:::color1 配置全局工具配置

:::

JDK 配置

02 Docker 实现CICD%26Docker 高级部分 - 图16

Maven 配置

02 Docker 实现CICD%26Docker 高级部分 - 图17

保存相应的配置即可!

:::color1 安装插件

:::

管理Jenkins→系统配置→管理插件→搜索git/pipeline/blue ocean,选中点击安装。默认从国外网络下载插件,会比较慢,建议修改国内源:

  1. $ docker exec -it jenkins /bin/bash
  2. cd /var/jenkins_home/updates
  3. # sed -i 's/https:\/\/updates.jenkins.io\/download/http:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' /var/lib/jenkins/updates/default.json
  4. # sed -i 's/https:\/\/www.google.com/https:\/\/www.baidu.com/g' /var/lib/jenkins/updates/default.json
  5. sed -i 's/https:\/\/updates.jenkins.io\/download/http:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' /var/jenkins_home/updates/default.json
  6. sed -i 's/https:\/\/www.google.com/https:\/\/www.baidu.com/g' /var/jenkins_home/updates/default.json
  7. $ docker restart jenkins

4.3.7 Jenkins 创建项目

系统管理 → 系统设置:主要配置workspace目录,全局环境变量,邮件通知,其他插件配置等。

系统管理 → Global Tool Confi guration:主要配置JDK、Maven等工具。

在系统设置里面先配置好SSH连接各个部署节点信息,在创建项目中使用。

4.3.7.1 测试节点:部署测试环境包( 测试节点 )

:::color1 下载测试部署压缩包

:::

  1. 目录结构
  2. ├── config
  3. # 生产环境配置文件
  4. ├── prod.html
  5. ├── prod.tar.gz
  6. # 测试环境配置文件
  7. ├── test.html
  8. └── test.tar.gz
  9. # 部署LNMP项目
  10. ├── deploy.sh
  11. # 编排描述内容
  12. ├── docker-compose.yml
  13. # 构建镜像
  14. ├── Dockerfile
  15. ├── nginx
  16. └── php
  17. # 将容器目录数据库持久化到该目录下
  18. ├── mysql_data
  19. # 推送镜像到线上使用
  20. ├── push_images.sh
  21. # 记录部署时的代码版本号
  22. ├── revision.svn
  23. # 存放项目目录
  24. └── wwwroot
  25. # 查看测试环境的页面
  26. $ cat config/test.html
  27. <h1>test</h1>
  28. # 查看生产环境的页面
  29. $ cat config/prod.html
  30. <h1>prod</h1>

4.3.7.2 解压文件,脚本加入执行权限,并查看相关文件信息( 测试节点 )

  1. # 上传test.zip脚本,解压缩
  2. unzip lnmp.zip;cd lnmp
  3. # 将脚本添加执行权限
  4. chmod +x push_images.sh

脚本 deploy.sh

  1. #!/bin/bash
  2. # 修订版本号
  3. REVISION=$1
  4. # 工作环境变量环境,test传入构建dockerfile内
  5. WORK_ENV=test
  6. # 将当前版本写入revison文件中
  7. echo $REVISION >./revision.svn
  8. # 进入Dockerfile
  9. cd Dockerfile
  10. # 构建镜像build传入test环境
  11. sudo docker build --build-arg work_env=$WORK_ENV -t lnmp-nginx:latest -f nginx ../
  12. sudo docker build --build-arg work_env=$WORK_ENV -t lnmp-php:latest -f php ../
  13. # 删除当前容器所有内容
  14. sudo docker-compose down
  15. # 重启初始化容器
  16. sudo docker-compose up -d
  17. # 脚本deploy.sh

docker-compose 脚本

  1. # 版本号
  2. version: '3'
  3. # 服务管理
  4. services:
  5. # nginx服务
  6. nginx:
  7. # 镜像使用仓库内镜像
  8. image: lnmp-nginx:latest
  9. # 暴露端口为80
  10. ports:
  11. - 80:80
  12. # 映射服务别名
  13. links:
  14. - php:php-cgi
  15. depends_on:
  16. - php
  17. - mysql
  18. # php服务
  19. php:
  20. # 镜像使用仓库内镜像
  21. image: lnmp-php:latest
  22. # 映射服务别名
  23. links:
  24. - mysql:mysql-db
  25. # mysql服务
  26. mysql:
  27. # 镜像版本
  28. image: mysql:5.6
  29. # 暴露端口
  30. ports:
  31. - 3306:3306
  32. # 映射服务数据卷
  33. volumes:
  34. - ./mysql_data:/var/lib/mysql
  35. command: --character-set-server=utf8
  36. # 指定数据库变量
  37. environment:
  38. MYSQL_ROOT_PASSWORD: 123456
  39. MYSQL_DATABASE: wordpress
  40. MYSQL_USER: user
  41. MYSQL_PASSWORD: user123
  42. # docker-compose脚本

Dockerfile 内的 Nginx 脚本

  1. # 指定镜像
  2. FROM 10.0.0.30:5000/lnmp-nginx:base
  3. # 指定管理员
  4. MAINTAINER xiangsikai
  5. # 接收构建参数
  6. ARG work_env
  7. # 更新网站目录
  8. ADD wwwroot /usr/local/nginx/html
  9. # 解压 接收参数传入变量的压缩包
  10. ADD config/${work_env}.tar.gz /usr/local/nginx/html
  11. # 声明暴露端口
  12. expose 80
  13. # Dockerfile 内 Nginx脚本

Dockerfile 内的 PHP 脚本

  1. # 指定镜像
  2. FROM 10.0.0.30:5000/lnmp-php:base
  3. # 指定管理员
  4. MAINTAINER xiangsikai
  5. # 接收构建参数
  6. ARG work_env
  7. # 更新网站目录
  8. ADD wwwroot /usr/local/nginx/html
  9. # 解压 接收参数传入变量的压缩包
  10. ADD config/${work_env}.tar.gz /usr/local/nginx/html
  11. # 声明暴露端口
  12. expose 9000
  13. # Dockerfile 内 PHP脚本

push_images.sh 脚本

  1. #!/bin/bash
  2. # 指定镜像仓库地址
  3. IMAGE_REPOS=10.0.0.30:5000
  4. # 记录部署时修订版本号
  5. REVISION=$(cat revision.svn)
  6. # 声明生产环境
  7. WORK_ENV=prod
  8. # 进入Dockerfile
  9. cd Dockerfile
  10. # 构建镜像build传入prod环境
  11. sudo docker build --build-arg work_env=$WORK_ENV -t $IMAGE_REPOS/lnmp-nginx:$REVISION -f nginx ../
  12. sudo docker build --build-arg work_env=$WORK_ENV -t $IMAGE_REPOS/lnmp-php:$REVISION -f php ../
  13. # 将镜像上传到镜像仓库
  14. sudo docker push $IMAGE_REPOS/lnmp-nginx:$REVISION
  15. sudo docker push $IMAGE_REPOS/lnmp-php:$REVISION
  16. # 注:通过jenkins在svn中自动拉取传入wwwroot目录下。
  17. # push_images.sh脚本

4.3.7.3 生产节点:部署生产环境包( 生产节点 )

  1. 目录结构
  2. ├── deploy.sh
  3. ├── docker-compose.yml
  4. ├── revision.svn
  5. └── roll-back.sh

4.3.7.4 解压文件,脚本加入执行权限,并查看相关文件信息( 生产节点 )

  1. # 解压文件,进入路径下
  2. unzip lnmp2.zip;cd lnmp
  3. # 加入文件执行权限
  4. chmod +x deploy.sh roll-back.sh

deploy.sh 脚本

  1. #!/bin/bash
  2. # 文件赋值变量
  3. REVISION=revision.svn
  4. # 镜像仓库位置
  5. IMAGE_REPOS=http://10.0.0.30:5000/v2
  6. # 获取最新镜像tag,取最大最新版本号
  7. LATEST_REVISION=$(curl $IMAGE_REPOS/lnmp-nginx/tags/list |\
  8. grep -Po '(?<=")\d+(?=")' |\
  9. awk 'BEGIN{max=0}{for(i=1;i<=NF;i++)if($i>max)max=$i}END{print max}')
  10. # 修改版本号到docker-compose内指定构建版本
  11. sed -i -r '/:5000/s/[0-9]+$/'$LATEST_REVISION'/' docker-compose.yml
  12. # 标记上一个版本和当前版本
  13. if ! grep "^$LATEST_REVISION " $REVISION &>/dev/null; then
  14. sed -i -r '$s/([0-9]+).*/\1 Previous/' $REVISION
  15. echo "$LATEST_REVISION Current" >> $REVISION
  16. fi
  17. # 重新部署docker-compose文件
  18. sudo docker-compose down
  19. sudo docker-compose up -d
  20. # deploy.sh脚本

docker-compose.yml 脚本

  1. version: '3'
  2. services:
  3. nginx:
  4. image: 10.0.0.30:5000/lnmp-nginx:12
  5. ports:
  6. - 80:80
  7. links:
  8. - php:php-cgi
  9. depends_on:
  10. - php
  11. php:
  12. image: 10.0.0.30:5000/lnmp-php:12
  13. links:
  14. - mysql:mysql-db
  15. mysql:
  16. image: mysql:5.6
  17. ports:
  18. - 3306:3306
  19. volumes:
  20. - ./mysql_data:/var/lib/mysql
  21. command: --character-set-server=utf8
  22. environment:
  23. MYSQL_ROOT_PASSWORD: 123456
  24. MYSQL_DATABASE: wordpress
  25. MYSQL_USER: user
  26. MYSQL_PASSWORD: user123
  27. # docker-compose.yml脚本

roll-backup.sh 脚本

  1. #!/bin/bash
  2. # 修改为上一个镜像版本
  3. PRE_REVISION=$(awk '/Previous/{revision=$1}END{print revision}' revision.svn)
  4. sed -i -r '/:5000/s/[0-9]+$/'$PRE_REVISION'/' docker-compose.yml
  5. # 当前有问题的版本记录
  6. sed -i '$d' revision.svn
  7. sudo docker-compose down
  8. sudo docker-compose up -d
  9. # roll-back.sh脚本

4.3.8 管理节点:Jenkins 安装

:::color1

注:Jenkins安装需要依赖JDK环境,为了也可以部署JAVA项目同样也安装了maven。 注:Jenkins同样也需要通过Tomcat来运行 通过平台化方式管理。

:::

4.3.8.1 安装 JDK 和 Maven 并配置环境变量

  1. # 解压jdk
  2. tar zxvf jdk-8u181-linux-x64.tar.gz
  3. # 移动jdk目录
  4. mv jdk1.8.0_181 /usr/local/jdk1.8
  5. # 解压maven
  6. tar zxvf apache-maven-3.6.0-bin.tar.gz
  7. # 移动jdk目录
  8. mv apache-maven-3.6.0 /usr/local/maven3.6

4.3.8.2 配置JDK 和 Maven 环境变量,并设置立即生效

  1. cat >> /etc/profile <<-'EOF'
  2. # Jenkins ENV BEGIN
  3. JAVA_HOME=/usr/local/jdk1.8
  4. CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
  5. MAVEN_HOME=/usr/local/maven3.6
  6. PATH=$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH
  7. export JAVA_HOME CLASSPATH MAVEN_HOME PATH
  8. # Jenkins ENV END
  9. EOF
  1. # 立刻生效
  2. source /etc/profile

4.3.8.3 部署 Tomcat

  1. # 解压tomcat
  2. tar zxvf apache-tomcat-8.0.53.tar.gz
  3. # 运行tomcat
  4. /root/apache-tomcat-8.0.53/bin/startup.sh
  5. # 删除目录下默认网站数据
  6. cd apache-tomcat-8.0.53/webapps;rm -rf ./*

4.3.8.4 添加 Jenkins 资源

  1. # 进入网站目录
  2. cd /root/apache-tomcat-8.0.53/webapps
  3. # 解压jenkins到指定ROOT目录
  4. unzip /root/jenkins.zip -d ROOT
  1. # 查看生成随机秘钥文件路径
  2. /root/.jenkins/secrets/initialAdminPassword

02 Docker 实现CICD%26Docker 高级部分 - 图18

4.3.8.5 Jenkins 安装

浏览器访问:http://10.0.0.30:8080

02 Docker 实现CICD%26Docker 高级部分 - 图19

02 Docker 实现CICD%26Docker 高级部分 - 图20

选择相关软件确认后install

  1. 安装ssh插件

02 Docker 实现CICD%26Docker 高级部分 - 图21

  1. 安装Git插件

02 Docker 实现CICD%26Docker 高级部分 - 图22

  1. 安装svn插件

02 Docker 实现CICD%26Docker 高级部分 - 图23

初始化install 安装

02 Docker 实现CICD%26Docker 高级部分 - 图24

根据 Jenkins 引导过程进行安装( 添加用户,确认执行Jenkins )

:::color1 若出现 Jenkins 版本过低,导致插件安装不上,需要管理员将Jenkins的版本提高。( 使用Docker部署 )

:::

  1. # docker pull jenkins/jenkins:lts
  2. docker pull jenkins/jenkins:2.375.1-lts
  3. docker run -d --name jenkins -p 80:8080 -p 50000:50000 -u root \
  4. -v /opt/jenkins_home:/var/jenkins_home \
  5. -v /var/run/docker.sock:/var/run/docker.sock \
  6. -v /usr/bin/docker:/usr/bin/docker \
  7. -v /usr/local/maven:/usr/local/maven \
  8. -v /usr/local/jdk:/usr/local/jdk \
  9. -v /etc/localtime:/etc/localtime \
  10. --restart=always \
  11. --name jenkins jenkins/jenkins:2.375.1-lts
  12. # 查看Jenkins日志
  13. $ docker logs -f jenkins
  14. # 查看Jenkins的进程信息
  15. $ docker ps -l
  16. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  17. 3a70a5fa86cc jenkins/jenkins:2.375.1-lts "/usr/bin/tini -- /u…" 50 seconds ago Up 49 seconds 0.0.0.0:50000->50000/tcp, 0.0.0.0:80->8080/tcp jenkins

4.3.8 Jenkins 自动发布

4.3.8.1 WordPress 自动发布到测试环境

02 Docker 实现CICD%26Docker 高级部分 - 图25

  • 设置构建最大的保留数

02 Docker 实现CICD%26Docker 高级部分 - 图26

  • SVN 的添加( 配置SVN的凭证 )

02 Docker 实现CICD%26Docker 高级部分 - 图27

02 Docker 实现CICD%26Docker 高级部分 - 图28

  • 在构建时进行配置( 需要配置该Server的凭证 )[ 传输 ]

02 Docker 实现CICD%26Docker 高级部分 - 图29

  • 保存后,进行 Jenkins 的构建

4.3.8.2 提交测试镜像到镜像仓库

4.3.8.3 自动发布到生产环境

5 Docker 结合 Consul 实现服务发现

5.1 Consul 是什么

Consul是:一个分布式、高可用性,在基础设施中发现和配置服务的工具。Consul 简化了分布式环境中的服务的注册和发现流程,通过 HTTP 或者 DNS 接口发现。支持外部 SaaS 提供者等。

在线演示:http://demo.consul.io/ui/ :::color1 Consul是HashiCorp公司推出的开源软件,基于 GO 语言编写,提供服务注册和发现、配置、多数据中心的高可用方案等能力,分布式一致方面采用 raft 算法实现,并且很容易和 Spring Cloud 等微服务框架集成,使用起来非常简单,具有简单、易用、可插排等特点。 简而言之,Consul 是服务网格的控制平面,Consul 提供了一种完整的服务网格解决方案。 ::: 主要功能: + 服务发现 通过DNS或HTTP接口使得消费者发现服务,应用程序可以轻松找到所依赖的服务。 + 健康检查 防止将请求转发不健康的主机。 + 键值存储 可以使用分层键/值存储,比如功能标记、动态配置等。 + 多数据中心 开箱即用,不需要复杂的配置。这就以为这不用建立抽象的逻辑来扩展多个地区。 + Web UI Consul为其用户提供了一个漂亮的Web界面,使用它可以很容易地使用和管理领事中的所有功能。

:::color1

与Etcd和Zookeeper的比较

:::

当我们查看此域中的其他服务发现工具时,我们有两个流行的选项。软件行业的一些主要参与者过去一直在使用它.这些工具是 Etcd Zookeeper。 让我们考虑下表来比较每个工具的不同方面,我们还将了解每个内部使用的内容。
属性 Consul Etcd Zoo Keeper
用户界面 可用 02 Docker 实现CICD%26Docker 高级部分 - 图30 02 Docker 实现CICD%26Docker 高级部分 - 图31
RPC 可用 可用 02 Docker 实现CICD%26Docker 高级部分 - 图32
运行状况检查 HTTP API HTTP API TCP
键值 3一致性模式 良好的一致性 强一致性
令牌系统 可用 02 Docker 实现CICD%26Docker 高级部分 - 图33 02 Docker 实现CICD%26Docker 高级部分 - 图34
语言 Golang Golang Java

5.2 Consul 集群介绍

:::color1 02 Docker 实现CICD%26Docker 高级部分 - 图35

我们只看数据中心1,可以看出consul的集群是由N个SERVER,加上M个CLIENT组成的。而不管是SERVER还是CLIENT,都是consul的一个节点,所有的服务都可以注册到这些节点上,正是通过这些节点实现服务注册信息的共享。除了这两个,还有一些小细节,一一简单介绍。 CLIENT CLIENT表示consul的client模式,就是客户端模式。是consul节点的一种模式,这种模式下,所有注册到当前节点的服务会被转发到SERVER,本身是不持久化这些信息。 SERVER SERVER表示consul的server模式,表明这个consul是个server,这种模式下,功能和CLIENT都一样,唯一不同的是,它会把所有的信息持久化的本地,这样遇到故障,信息是可以被保留的。 SERVER-LEADER 中间那个SERVER下面有LEADER的字眼,表明这个SERVER是它们的老大,它和其它SERVER不一样的一点是,它需要负责同步注册的信息给其它的SERVER,同时也要负责各个节点的健康监测。 其它信息其它信息包括它们之间的通信方式,还有一些协议信息,算法。它们是用于保证节点之间的数据同步,实时性要求等等一系列集群问题的解决。这些有兴趣的自己看看官方文档

:::

1)Consul agent 是Consu1核心工作,分为client和server两种工作模式。默认以client模式运行,提供服务注册、健康检查、转发查询给server leader. server模式启动时使用-server选项指定,用于维护Consul集群状态 Raft协议进行选举。

2)agent必须在每个Consul节点运行,所有运行Consul agent 节点构成Consul集群。

3)官方建议Consul集群至少3或5个节点运行Consul agent server模式, client 节点不限。

4)通过join 或 rejoin 选项加入集群。一旦加入, 集群信息使用 gossip 算法同步到整个集群节点。

:::color1

Raft算法 Raft是用于管理复制日志的一致性算法.它依赖于 **CAP定理**的原理,该原理指出在存在网络分区时,必须在一致性和可用性之间进行选择.并非CAP定理的所有三个基本原理都可以在任何给定的时间点实现.必须在最好的情况下权衡其中任何两个. A Raft群集包含多个服务器,通常是奇数计数.例如,如果我们有五台服务器,它将允许系统容忍两个故障.在任何给定时间,每个服务器都处于以下三种状态之一:领导者,追随者候选人.在正常操作中,只有一个领导者,所有其他服务器都是粉丝.这些粉丝处于被动状态,即他们自己不发出请求,只是回应领导者和候选人的请求. 下图描述了使用筏子的工作流模型算法工作 :

02 Docker 实现CICD%26Docker 高级部分 - 图36

:::

5.3 Consul 集群部署

官方文档:

https://www.consul.io/docs/install#precompiled-binaries

https://learn.hashicorp.com/tutorials/consul/deployment-guide?in=consul/production-deploy#configure-consul-agents

https://github.com/hashicorp/consul

02 Docker 实现CICD%26Docker 高级部分 - 图37

下载二进制Consul包: https://www.consul.io/downloads.html

安装二进制包:

  1. # wget https://releases.hashicorp.com/consul/1.14.2/consul_1.14.2_linux_amd64.zip
  2. $ unzip consul_0.9.2_linux_amd64.zip
  3. $ mv consul /usr/bin
  4. # 官方部署文档
  5. # Ubuntu
  6. # wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
  7. # echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
  8. # sudo apt update && sudo apt install consul
  9. # CentOS
  10. # sudo yum install -y yum-utils
  11. # sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
  12. # sudo yum -y install consul

Consul Server 模式初始化集群:

  1. # 以下命令执行为前台执行
  2. $ consul agent \
  3. -server \
  4. -bootstrap \
  5. -ui \
  6. -data-dir=/var/lib/consul-data \
  7. -bind=10.0.0.30 \
  8. -client=0.0.0.0 \
  9. -node=master
  10. # -node 不指定则是默认主机名[ 必须是集群唯一的 ]
  11. # 后台启动Consul
  12. $ nohup consul agent \
  13. -server \
  14. -bootstrap \
  15. -ui \
  16. -data-dir=/var/lib/consul-data \
  17. -bind=10.0.0.30 \
  18. -client=0.0.0.0 \
  19. -node=master &
  20. # 查看Consul的成员
  21. $ consul members
  22. Node Address Status Type Build Protocol DC Partition Segment
  23. master 10.0.0.30:8301 alive server 1.14.2 2 dc1 default <all>

:::color1 Consul 常用命令

:::

  1. consul agent -dev #该命令启动只能允许本机访问
  2. consul agent -dev -client 0.0.0.0 # 加上-client 0.0.0.0就可以其他机器进行访问了
  3. # 进入consulserver容器
  4. kubectl exec -it consul-server-0 -- /bin/sh
  5. # 查看成员
  6. consul members
  7. # 查看版本号
  8. consul version
  9. # 列出所有服务
  10. consul catalog services -http-addr=localhost:8500
  11. # 列出consul的信息
  12. consul info

Consul Client模式加入集群:

  1. # Node01(10.0.0.31)节点执行
  2. $ docker run -d \
  3. --name=consul \
  4. -p 8301:8301 \
  5. -p 8301:8301/udp \
  6. -p 8500:8500 \
  7. -p 8600:8600 \
  8. -p 8600:8600/udp \
  9. --restart=always \
  10. progrium/consul \
  11. -join 10.0.0.30 -advertise 10.0.0.31 -client 0.0.0.0 -node=node01
  12. # Node02(10.0.0.32)节点执行
  13. $ docker run -d \
  14. --name=consul \
  15. -p 8301:8301 \
  16. -p 8301:8301/udp \
  17. -p 8500:8500 \
  18. -p 8600:8600 \
  19. -p 8600:8600/udp \
  20. --restart=always \
  21. progrium/consul \
  22. -join 10.0.0.30 -advertise 10.0.0.32 -client 0.0.0.0 -node=node02
  23. # 查看Consul的日志
  24. $ docker logs consul
  1. # Consul Cluster 查看端口
  2. $ docker port consul
  3. 8301/tcp -> 0.0.0.0:8301
  4. 8600/udp -> 0.0.0.0:8600
  5. 8500/tcp -> 0.0.0.0:8500
  6. 8600/tcp -> 0.0.0.0:8600
  7. 8301/udp -> 0.0.0.0:8301
  8. # Consul Master 节点查看成员
  9. $ consul members
  10. Node Address Status Type Build Protocol DC Partition Segment
  11. master 10.0.0.30:8301 alive server 1.14.2 2 dc1 default <all>
  12. node01 10.0.0.31:8301 alive client 0.5.2 2 dc1 default <default>
  13. node02 10.0.0.32:8301 alive client 0.5.2 2 dc1 default <default>
  14. # 集群就部署完毕

可以使用 Consul 的WebUI 查看 Consul 情况。默认WebUI端口为 8500

02 Docker 实现CICD%26Docker 高级部分 - 图38

查看Consul 集群的节点的情况

02 Docker 实现CICD%26Docker 高级部分 - 图39

范例:查看集群信息

  1. $ consul members
  2. Node Address Status Type Build Protocol DC Partition Segment
  3. master 10.0.0.30:8301 alive server 1.14.2 2 dc1 default <all>
  4. node01 10.0.0.31:8301 alive client 0.5.2 2 dc1 default <default>
  5. node02 10.0.0.32:8301 alive client 0.5.2 2 dc1 default <default>
  6. $ consul info | grep leader
  7. leader = true
  8. leader_addr = 10.0.0.30:8300
  9. $ consul catalog services
  10. consul

通过HTTP API 获取集群信息

  1. curl 127.0.0.1:8500/v1/status/peers # 集群成员
  2. curl 127.0.0.1:8500/v1/status/leader # 集群Raft leader
  3. eurl 127.0.0.1:8500/v1/catalog/services #注册的所有服务
  4. curl 127.0.0.1:8500/v1/catalog/services/nginx #服务信息
  5. curl 127.0.0.1:8500/v1/catalog/nodes # 集群节点详细信息

服务注册

  1. curl -x PUT -d \
  2. '{"id": "jetty", "name": "service_name”, "address": "10.0.0.32”,"port”: 8080,”tags": ["test"], "checks":
  3. [{"http": "http://10.0.0.32:8080/*, "interval": "5s"}]}' \
  4. http://127.0.0.1:8500/v1/agent/service/register
类型 描述
kv 键值存储
agent agent管理
catalog nodes和services管理
health 健康检查
session session管理
acl ACL管理
event 用户事件
status Consul系统状态

5.4 附录:consul 常用命令

附1 consul常用命令+常用选项

之后每用到一个command或options,都会记录在这里。

常用命令**command**

  • agent - 作用:运行一个consul agent
  • join - 作用:将agent加入到consul cluster
  • members - 作用:列出consul cluster集群中的members

常用选项**option**

  • -data-dir - 作用:指定agent储存状态的数据目录 - 这是所有agent都必须的 - 对于server尤其重要,因为他们必须持久化集群的状态
  • -config-dir - 作用:指定service的配置文件和检查定义所在的位置 - 通常会指定为”某一个路径/consul.d”(通常情况下,.d表示一系列配置文件存放的目录)
  • -config-file - 作用:指定一个要装载的配置文件 - 该选项可以配置多次,进而配置多个配置文件(后边的会合并前边的,相同的值覆盖)
  • -dev - 作用:创建一个开发环境下的server节点 - 该参数配置下,不会有任何持久化操作,即不会有任何数据写入到磁盘 - 这种模式不能用于生产环境(因为第二条)
  • -bootstrap-expect - 作用:该命令通知consul server我们现在准备加入的server节点个数,该参数是为了延迟日志复制的启动直到我们指定数量的server节点成功的加入后启动。
  • -node - 作用:指定节点在集群中的名称 - 该名称在集群中必须是唯一的(默认采用机器的host) - 推荐:直接采用机器的IP
  • -bind - 作用:指明节点的IP地址
  • -server - 作用:指定节点为server - 每个数据中心(DC)的server数推荐为3或5(理想的是,最多不要超过5) - 所有的server都采用raft一致性算法来确保事务的一致性和线性化,事务修改了集群的状态,且集群的状态保存在每一台server上保证可用性 - server也是与其他DC交互的门面(gateway)
  • -client - 作用:指定节点为client - 若不指定为-server,其实就是-client
  • -join - 作用:将节点加入到集群
  • -domain
  • -dc - 作用:指定机器加入到哪一个dc中 - 例子:

02 Docker 实现CICD%26Docker 高级部分 - 图40

选项 描述
-advertise 通告地址
-bind 集群节点之间通信地址
-bootstrap 设置服务器为bootstrap模式。在一个dc中只有一个server处于bootstrap模式。一般初始化第一台Consul时 指定,自选举为leader。
-bootstrap-expect 在一个dc中期望提供server节点数目,consul会 一直等到指定的server数目才会引导整个集群,选举leader.不能与boostrap同时用。
-client 设置客户端访问地址,包括RPC、DNS。默认127.0.0.1
-config-file 从JSON配置文件中读取
-data-dir 指定存放agent server集群状态目录,以免系统重启丢失
-dc 数据中心名称,默认dc1
-http-port HTTP API监听端口
-join 加入一个已经启动的agent,可以指定多个agent地址
-node 节点名称,必须在集群中唯一的。默认是主机名
-rejoin 忽略先前的离开,再次启动后尝试加入集群
-server 切换agent模式到server模式。每个集群至少有个server
-ui 启用内置的Web UI
-ui-dir Web UI的资源目录

5.5 Docker + Registrator + Consul 实现 Nginx 集群节点自动加入

Reference:

https://github.com/hashicorp/consul-template

https://releses.hashicorp.com/consul-template/0.19.3/consul-template_0.19.3_linux_amd64.zip

02 Docker 实现CICD%26Docker 高级部分 - 图41

  • consul-template:一个守护程序,用于实时查询consul集群数据,并更新文件系统上的任意数量的指定模板,生成配置文件,更新完成后可以选择运行任何命令。

:::color1

Consul-template 是一个守护进程,用于实时查询consul集群信息,并更新文件系统上任意数量的指定模板,生成配置文件。更新完成以后,可以选择运行shell命令执行更新操作,重新加载Nginx。Consul-Template可以查询Consul中的服务目录、Key、Key-values等。 这种强大的抽象功能和查询语言模板可以是Consul-Template 特别适合动态的创建配置文件。 例如:创建 Apache/Nginx Proxy Balancers、Haproxy Backends

:::

  • gliderlabs/registrator:检查容器运行状态自动注册到服务中心。
    • registrator 支持服务注册有consul、etcd、SkyDNS2。
  1. $ wget https://releases.hashicorp.com/consul-template/0.25.0/consul-template_0.25.0_linux_amd64.zip
  2. $ unzip consul-template_0.25.0_linux_amd64.zip
  3. $ mv consul-template /usr/bin/
  4. $ consul-template -v
  5. consul-template v0.25.0 (99efa642)

Node节点启动注册服务:

  1. # 格式
  2. $ docker run -d \
  3. --name=registrator \
  4. -v /var/run/docker.sock:/tmp/docker.sock \
  5. --restart=always \
  6. gliderlabs/registrator:latest \
  7. consul://<Docker Host IP>:8500
  8. # Node01(10.0.0.31) 和 Node02(10.0.0.32)执行
  9. $ docker run -d \
  10. --name=registrator \
  11. -v /var/run/docker.sock:/tmp/docker.sock \
  12. --restart=always \
  13. gliderlabs/registrator:latest \
  14. consul://10.0.0.31:8500
  15. $ docker run -d \
  16. --name=registrator \
  17. -v /var/run/docker.sock:/tmp/docker.sock \
  18. --restart=always \
  19. gliderlabs/registrator:latest \
  20. consul://10.0.0.32:8500
  21. # 查看registrator的进程
  22. $ docker ps -l
  23. CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
  24. 788cc85312ac gliderlabs/registrator:latest "/bin/registrator co…" 19 seconds ago Up 18 seconds registrator

可以在Consul WebUI界面查看配置Service 服务状态

02 Docker 实现CICD%26Docker 高级部分 - 图42

范例:在10.0.0.31-Node01 和 10.0.0.32-Node02启动Nginx容器测试

  1. $ docker run -it -d -P --name nginx-node01 nginx:1.21.6-alpine

02 Docker 实现CICD%26Docker 高级部分 - 图43

02 Docker 实现CICD%26Docker 高级部分 - 图44

可以访问其注册的IP地址:Port端口就可以访问其 Nginx 默认页面

  1. # 在10.0.0.30部署Nginx
  2. rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
  3. yum -y install nginx
  4. systemctl enable --now nginx
  5. # /etc/nginx/nginx.conf //yum方式安装后默认配置文件的路径
  6. # /usr/share/nginx/html //nginx网站默认存放目录
  7. # /usr/share/nginx/html/index.html //网站默认主页路径
  1. tee > nginx.ctmpl <<EOF
  2. upstream http_backend {
  3. ip_hash;
  4. # 镜像名字
  5. {{range service "nginx"}}
  6. server {{ .Address }}:{{ .Port }};
  7. {{ end }}
  8. }
  9. server {
  10. listen 80;
  11. # server_name www.nextdevops.cn;
  12. server_name localhost;
  13. location / {
  14. proxy_pass http://http_backend;
  15. }
  16. }
  17. EOF
  18. # 格式:
  19. # consul-template \
  20. # -consul-addr <Consul server>:8500 \
  21. # -template "./nginx.ctmpl:/usr/local/nginx/conf/nginx.conf:/usr/local/nginx/sbin/nginx -s reload" \
  22. # -log-level=info
  23. $ consul-template \
  24. -consul-addr 10.0.0.30:8500 \
  25. -template "./nginx.ctmpl:/etc/nginx/conf.d/nginx.conf:/usr/sbin/nginx -s reload" \
  26. -log-level=info
  27. # 会追踪相应的日志(会显示服务发现的功能)
  28. $ cat /etc/nginx/conf.d/nginx.conf
  29. upstream http_backend {
  30. ip_hash;
  31. # 镜像名字
  32. server 10.0.0.31:32770;
  33. server 10.0.0.32:32769;
  34. }
  35. server {
  36. listen 80;
  37. # server_name www.nextdevops.cn;
  38. server_name localhost;
  39. location / {
  40. proxy_pass http://http_backend;
  41. }
  42. }

6 Docker API

Old Docker Reference:

http://dockone.io/article/107

http://dockerone.com/article/109

http://dockerone.com/article/110

New Docker Reference:

https://blog.51cto.com/u_15346415/4985683

https://blog.51cto.com/u_15346415/4985680

6.1 Docker API 介绍

Docker提供了Docker Engine API与Docker daemon交互,Docker提供了Go和Python版本的SDK。本质上Docker Engine API是一个RESTful的接口,可以通过HTTP请求操作。

02 Docker 实现CICD%26Docker 高级部分 - 图45

Docker提供了很多的API以便用户使用。这些API包含四个方面:
  • Docker Registry API
  • Docker Hub API
  • Docker OAuth API (使用较少)
  • Docker Remote API

:::color1 1. Docker Registry API

这个是docker镜像仓库的api,通过操作这套API,你可以自由的自动化、程序化的管理你的镜像仓库。

2. Docker Hub API

Docker Hub API是用户管理操作的API,docker hub是使用校验和公共 namespaces 的方式来存储账户信息、认证账户、进行账户授权。API同时也允许操作相关的用户仓库和 library 仓库。

3. Docker Remote API

这套API用于控制主机 Docker 服务端的 API,等价于 docker命令行客户端。 有了它,你能远程操作docker容器,更重要的是你可以通过程序自动化运维docker进程。

:::

6.2 初始 Remote API

Remote API是由Docker守护进程提供的

:::color1 守护进程的默认套接字

:::

默认的情况下,Docker守护进程会绑定到一个所在宿主机的套接字,即unix:///var/run/docker.sock

02 Docker 实现CICD%26Docker 高级部分 - 图46

:::color1 Docker守护进程的默认配置文件

:::

不同系统中,Docker守护进程的默认配置文件为:

Ubuntu、Debian系统:/etc/default/docker

Upstart系统:/etc/init/docker.conf

Red Hat、Redora系统:/etc/sysconfig/docker

对于那些使用了Systemd的发布版本:/usr/lib/systemd/docker.service

:::color1 演示机器是Ubuntu 20.04 系统版本,查看如下

:::

  1. sudo cat /etc/default/docker

02 Docker 实现CICD%26Docker 高级部分 - 图47

备注(重点):docker安装在桌面版ubuntu的时候,默认的配置文件/etc/default/docker里的配置是无效的(server版并无问题),导致之前的很多工作进展缓慢,这个问题在官方文档中有出现

:::color1 访问Docker API

:::

我们可以输入下面的命令来模仿一个客户端,来访问Docker守护进程

  1. echo -e "GET /info HTTP/1.0\r\n" | sudo nc -U /var/run/docker.sock

02 Docker 实现CICD%26Docker 高级部分 - 图48

:::color1 远程访问Remote API(改变守护进程监听地址)

:::

上面我们说了,守护进程默认绑定到unix:///var/run/docker.sock域套接字上,那么我们只能在本地来访问这个守护进程

如果我们想要让远程来访问我们主机的Remote API,那么就需要将Docker守护进程绑定到一个网络接口上

修改方法:修改配置文件,见下面演示案例

:::color1 接口更改演示案例

:::

下面我们使用的是桌面版本的ubuntu系统,因此/etc/default/docker配置文件不生效(但是server版本不会出现这种情况)

在这种情况下我们需要修改/lib/systemd/system/docker.service文件中的ExecStart选项,默认的情况如下

  1. sudo vim /lib/systemd/system/docker.service

02 Docker 实现CICD%26Docker 高级部分 - 图49

下面我们修改ExecStart选项,在尾部添加如下的内容,让其监听在0.0.0.0:2375地址上

02 Docker 实现CICD%26Docker 高级部分 - 图50

:::color1 备注:

前面还有一个-H选项,这个选项是让守护进程监听在默认的域套接字上

Docker允许守护进程监听在多个端口上,因此我们在后面又添加了一个-H,让其监听在tcp端口上

:::

首先重启Docker服务,然后再重启Docker守护进程

  1. sudo systemctl daemon-reload
  2. sudo service docker restart

查看一下守护进程的状态,可以看到守护进程监听在两个端口上

02 Docker 实现CICD%26Docker 高级部分 - 图51

现在我们既可以使用当初的域套接字来访问Docker(本地访问)

  1. sudo docker -H unix:///var/run/docker.sock info

02 Docker 实现CICD%26Docker 高级部分 - 图52

也可以使用公开的tcp服务来访问Docker(用于外网访问)

  1. sudo docker -H 10.0.0.100:2375 info

02 Docker 实现CICD%26Docker 高级部分 - 图53

客户端使用的DOCKER_HOST环境变量

上面我们看到了,客户端访问Docker时都需要使用-H来指定Docker的地址,比较麻烦

Docker提供了DOCKER_HOST环境变量,设置之后客户端就会去访问DCOERK_HOST环境变量所设置的Docker,不需要每次执行命令时都要-H选项了

例如,下面将DOCKER_HOST设置为我们上面指定的Docker服务地址

  1. sudo docker info

02 Docker 实现CICD%26Docker 高级部分 - 图54

备注:与Docker守护进程之间的网络连接是没有经过认证的,是对外开放的。本文后面会介绍如何为网络连接加入认证功能

6.3 测试 Docker Remote API

下面我们开始使用Docker的一些API来对Docker进行测试操作;都以curl命令来连接到Docker守护进程获取信息

例如,还是获取Docker的信息,命令如下:

Docker给我返回了Docker的信息,这些信息都是以JSON格式返回的

另外,由于默认的情况下,Docker返回的JSON数据都是非常乱的,因此我们在最后使用了Python的格式化工具对结果进行了格式化处理,看起来比较整洁(文本下面都会使用这个工具命令)

  1. curl http://10.0.0.100:2375/info | python -mjson.tool

02 Docker 实现CICD%26Docker 高级部分 - 图55

6.4 通过 API 管理Docker 镜像

6.4.1 获取镜像列表(/images/json)

想要获取Docker的镜像列表,可以输入下面的命令,结果如下所示:

  1. $ docker images
  2. REPOSITORY TAG IMAGE ID CREATED SIZE
  3. nginx latest 605c77e624dd 11 months ago 141MB
  4. redis latest 7614ae9453d1 11 months ago 113MB

结果返回了当前Docker的所有镜像,并且信息都比较详细

它们返回的结果与docker images命令非常类似

  1. curl http://10.0.0.100:2375/images/json | python -mjson.tool

02 Docker 实现CICD%26Docker 高级部分 - 图56

6.4.2 查看指定的镜像的信息(/images/ID/json)

我们也可以来查看指定的镜像的信息。例如:

  1. $ docker inspect nginx
  2. # 获取镜像的ID
  3. $ docker inspect -f "{{.Id}}" nginx
  4. sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
  5. # 将镜像运行成容器
  6. $ docker run -it -d --name nginx-node nginx
  7. b854eb7e61405abd265c9ab0b4508713f84340e520b258f4d9027ff3f0c5e4b7

我们有一个容器的ID为:sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85

下面我们来查看指定的镜像,就可以使用下面的命令

  1. curl http://10.0.0.100:2375/images/sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85/json | \
  2. python -mjson.tool

02 Docker 实现CICD%26Docker 高级部分 - 图57

可以看到,这种做法与用”docker inspect”命令来查看某一镜像的信息是十分类似的

6.4.3 搜索镜像(/images/search?term=xxx)

还可以使用Docker API从Docker Hub上搜索指定的镜像

例如,下面从Docker Hub上搜索镜像名字中带”jamtur01”的所有镜像

  1. curl "http://10.0.0.100:2375/images/search?term=jamtur01" | python -mjson.tool

02 Docker 实现CICD%26Docker 高级部分 - 图58

6.5 通过API管理Docker容器

6.5.1 查看所有的容器(/containers/json?all=1)

例如当前我们的系统中有这些容器

  1. sudo docker ps -a

02 Docker 实现CICD%26Docker 高级部分 - 图59

可以输入下面的命令来查看所有的容器(不论是否在运行)

  1. curl http://10.0.0.100:2375/containers/json?all=1 | \
  2. python -mjson.tool

02 Docker 实现CICD%26Docker 高级部分 - 图60

6.5.2 列出正在运行的容器(/containers/json)

例如当前系统中运行着一个Docker容器

  1. sudo docker ps

02 Docker 实现CICD%26Docker 高级部分 - 图61

可以输入下面的命令来查看当前系统中运行的容器,可以看到只有一个

  1. curl http://10.0.0.100:2375/containers/json | \
  2. python -mjson.tool

02 Docker 实现CICD%26Docker 高级部分 - 图62

6.5.3 创建容器(/containers/create)

可以输入下面的命来创建一个容器。命令如下:

使用了POST请求调用了/containers/create接入点来创建容器

POST了一个JSON散列数据,其中Images指定了要创建的容器的名称

创建完成之后命令会返回创建的容器的ID(9f450c13d90034a01fe81dba5a6c75ca5686476bea231118f43f5c203775b7e2)以及可能的警告信息

  1. curl -X POST -H "Content-Type:application/json" http://10.0.0.100:2375/containers/create -d '{ "Image":"redis:latest"}'

02 Docker 实现CICD%26Docker 高级部分 - 图63

来查看我们新创建的容器,可以看到ID与上面.的一致

  1. curl http://10.0.0.100:2375/containers/json?all=1 | python -mjson.tool

02 Docker 实现CICD%26Docker 高级部分 - 图64

通过下面的命令也可以看到新创建的容器

  1. sudo docker ps -a

02 Docker 实现CICD%26Docker 高级部分 - 图65

备注:当然,我们可以在创建容器时指定更多的信息,例如下面添加了一个容器的主机名

  1. curl -X POST -H "Content-Type:application/json" http://10.0.0.100:2375/containers/create -d '{ "Image":"redis:latest","Hostname":"dongshao"}'

6.5.4 启动容器

例如,我们可以输入下面的命令来启动上面我们创建的容器

  1. curl -X POST -H "Content-Type:application/json" http://10.0.0.100:2375/containers/9f450c13d90034a01fe81dba5a6c75ca5686476bea231118f43f5c203775b7e2/start -d '{ "PublishAllPorts":true}'

02 Docker 实现CICD%26Docker 高级部分 - 图66

7 Docker 日志管理

Docker容器日志分为两类:
  • Docker引擎日志(Docker本身运行的日志)
  • 容器日志(各个容器内产生的日志)

7.1 Docker引擎日志

Centos系统下的docker引擎日志一般给systemd管理,可通过<font style="color:#E8323C;">journalctl -u docker.service</font>命令查看

02 Docker 实现CICD%26Docker 高级部分 - 图67

7.2 容器日志

1、可通过<font style="color:rgb(0, 0, 0);">docker logs [容器ID]</font>命令显示当前运行的容器log,输出Linux下的STDOU、STDERR,生产环境中,如果应用输出到我们自己的日志文件里,使用<font style="color:rgb(0, 0, 0);">docker logs</font>一般收集步到太多重要信息。 2、docker日志驱动 Docker ce版本,Docker logs命令仅适用于如下驱动程序:

02 Docker 实现CICD%26Docker 高级部分 - 图68

常用的日志驱动主要有:json-file(默认)、local、syslog、journald、fluentd 1)查看docker日志驱动命令

02 Docker 实现CICD%26Docker 高级部分 - 图69

2)查看指定容器设置的日志驱动命令
  1. docker inspect -f "{{ .HostConfig.LogConfig.Type }}" [Container_ID]

02 Docker 实现CICD%26Docker 高级部分 - 图70

3)docker日志驱动全局配置文件为<font style="color:rgb(0, 0, 0);">/etc/docker/daemon.json</font> 4)日志驱动:local local日志驱动记录从容器的STDOUT/STDERR输出,并写到主机磁盘上。默认情况下,local日志驱动为每个容器保留100M的日志信息,并启用压缩来保存 local日志驱动存储于/var/lib/docker/containers/容器id/local-logs目录下,以container.log命名,local驱动支持的选项有:
  • max-size:切割之前日志的最大容量,可取值为k/m/g,默认20m
  • max-file:可以存在的最大日志文件个数,如果超过最大值,则会删除旧文件,仅在max-size选项设置时有效。默认为5
  • compress:对应切割日志文件是否启用压缩,默认启用
配置全局日志驱动为local时,需修改/etc/docker/daemon.json文件:
  1. {
  2. "log-driver": "local",
  3. "log-opts": {
  4. "max-size": "10m"
  5. }
  6. }
然后重启docker服务即可生效 对于指定容器设置为local驱动时,需在docker run中加—log-driver local选项即可 5)日志驱动json-file: json-file日志路径:<font style="color:rgb(0, 0, 0);">/var/lib/docker/containers/容器id/容器id-json.log</font> json-file日志驱动支持的驱动选项:
  • max-size:切割之前日志的最大大小。取值单位k/m/g,默认为-1(表示无限制)
  • max-file:存在的最大日志文件数,仅在max-size设置时有效,默认为1
  • labels:适用于启动docker守护进程时,此守护进程接受的以逗号分隔的与日志记录相关的标签列表
  • env:适用于启动docker守护进程时,此守护进程接手的以逗号分隔的与日志记录相关的环境变量列表
  • env-regex:类似并兼容env。用于匹配与日志记录相关的环境变量的正则表达式。
  • compress:切割的日志是否进行压缩。默认是disabled
6)日志驱动syslog: syslog日志驱动将日志路由到syslog服务器,syslog以原始的字符串作为日志消息元数据,接收方可以提取以下消息: debug、warning、error、info的日志level;timestamp时间戳、hostname事件发生的主机、facility系统模块、进程名和进程id 修改<font style="color:rgb(0, 0, 0);">/etc/docker/daemon.json</font>文件配置全局日志驱动为syslog:
  1. {
  2. "log-driver": "syslog",
  3. "log-opts": {
  4. "syslog-address": "udp://1.2.3.4:1111"
  5. }
  6. }