系统:ubuntu19.04
数据库:mysql5.7
git服务器:gogs
持续集成工具:jenkins
私有仓库:harbor
1.创建一个网络 1 2 3 4 5 # 创建 docker network create -d bridge --subnet=172.20.0.0/24 --gateway=172.20.0.1 deploy # 删除 docker network rm deploy
2.搭建gogs服务器 2.1 创建数据卷目录 1 2 3 sudo mkdir -p /var/jenkins/docker_mysql/data sudo mkdir -p /var/jenkins/docker_mysql/log sudo mkdir -p /var/jenkins/docker_gogs
2.2 编写docker-compose.yaml 文件存放路径~/jenkins/gogs
gogs初始化数据库时填写mysql的IP地址(172.20.0.2)
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 version: '3' services: mysql: container_name: mysql image: mysql:5.7 ports: - "3306:3306" environment: TZ: 'Asia/Shanghai' MYSQL_ROOT_PASSWORD: 123456 MYSQL_DATABASE: gogs MYSQL_USER: root MYSQL_PASSWORD: wyy123456 volumes: - /var/jenkins/docker_mysql/data:/var/lib/mysql - /var/jenkins/docker_mysql/log:/var/log/mysql restart: always command: mysqld --lower_case_table_names=1 --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci networks: deploy: ipv4_address: 172.20 .0 .2 gogs: container_name: gogs image: gogs/gogs:latest ports: - "10022:22" - "10080:3000" volumes: - /var/jenkins/docker_gogs:/data depends_on: - "mysql" restart: always environment: TZ: 'Asia/Shanghai' networks: deploy: ipv4_address: 172.20 .0 .3 networks: deploy: external: true
启动容器sudo docker-compose up -d
2.3 gogs初始化 访问 172.20.0.3:10080
配置数据库,填写数据库访问账号密码及ip
root wyy123456 172.20.0.2
设置gogs账号密码
gogs wyy123456
2.4 操作指令 1 2 3 4 5 6 7 8 9 10 11 sudo docker-compose stop sudo docker rm gogs mysql gitea # 删除gogs创建的网桥 sudo docker network rm gogs_gogs-network sudo rm -rf /var/docker_mysql/data /var/docker_mysql/log /var/docker_gogs/ /var/gitea/ # 查看docker网桥 sudo docker network ls sudo mkdir -p /var/docker_mysql/data /var/docker_mysql/log /var/docker_gogs/ /var/gitea/ sudo docker-compose up -d
3.搭建Registry仓库(改用harbor) docker仓库改成使用harbor,搭建harbor看文章《Harbor搭建私有docker registry》,需要自定义需要自行修改docker-compose.yaml
3.1 docker使用国内镜像进行加速 常用站点
1 2 3 4 5 6 https://registry.docker-cn.com http://hub-mirror.c.163.com https://3laho3y3.mirror.aliyuncs.com http://f1361db2.m.daocloud.io https://mirror.ccs.tencentyun.com http://mirrors.ustc.edu.cn/
编辑文件/etc/docker/daemon.json
insecure-registries指定私有仓库的ip:port
1 2 3 4 5 6 7 8 { "registry-mirrors": [ "https://registry.docker-cn.com", "http://hub-mirror.c.163.com", "https://docker.mirrors.ustc.edu.cn" ], "insecure-registries": ["127.0.0.1:5000"] }
重启docker daemon
1 2 $ sudo systemctl daemon-reload $ sudo systemctl restart docker
3.2 下载registry镜像 1 sudo docker pull registry:2
3.3 创建数据卷 1 2 sudo mkdir -p /var/docker_registry/data sudo mkdir -p /var/docker_registry/auth
3.4 创建用户授权文件 1 2 3 4 5 6 7 8 9 10 11 12 # username: wyy passwd: 123456 # root用户 sudo su sudo docker run --name create_auth --entrypoint htpasswd registry:2 -Bbn wyy 123456 >> /var/docker_registry/auth/htpasswd exit # delete tmp container sudo docker rm create_auth # show htpassed content cat /var/docker_registry/auth/htpasswd
3.5 编写docker-compose.yaml 文件存放路径/jenkins/registry
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 version: '3' services: registry: container_name: my-registry image: registry:2 ports: - "5000:5000" volumes: - /var/docker_registry/auth:/auth - /var/docker_registry/data/var/lib/registry/ restart: always environment: - REGISTRY_AUTH="htpasswd" - REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" - REGISTRY_AUTH_HTPASSWD_PATH="/auth/htpasswd" networks: deploy: ipv4_address: 172.18 .0 .5 networks: deploy: external: true
1 2 3 4 5 6 7 8 # 浏览器访问的时候需要填写账号密码 docker run -d -p 5000:5000 --restart=always --name my-registry \ -v /opt/docker-registry/auth:/auth \ -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \ -v /opt/docker-registry/data:/var/lib/registry/ \ registry
3.6 登录docker registry 1 2 3 # 账号密码是上一步创建 登录:sudo docker login -u wyy -p 123456 127.0.0.1:5000 退出:sudo docker logout 127.0.0.1:5000
3.7 验证是否运行成功 打开浏览器,访问下面的链接
1 127.0.0.1:5000/v2/_catalog
返回{"repositories":[]}说明正常
3.8 推送镜像到私有仓库 1 2 3 # 先登陆才能push docker tag nginx 127.0.0.1:5000/nginx docker push 127.0.0.1:5000/nginx
3.9 私有仓库拉取镜像到本地 1 docker pull 127.0.0.1:5000/nginx
4.搭建jenkins环境 4.1 构建jenkins容器 由于我们需要在jenkins容器中运行宿主机中的docker,并且需要调用ansible的命令,所以需要重新构建官方的jenkins容器。
1 2 3 4 5 6 7 8 9 10 11 sudo mkdir -p ~/jenkins/jenkins cd ~/jenkins/jenkins sudo wget https://repo.jenkins-ci.org/public/org/jenkins-ci/main/jenkins-war/2.199/jenkins-war-2.199.war # 构建镜像需要使用到 sha256sum jenkins-war-2.199.war # e5095ae6f8ccf7ef4934d7745f2e086a2e9e2a42a0e6777f009d3e54c8404b96 jenkins-war-2.199.war # 官方jenkins容器仓库 sudo git clone https://github.com/jenkinsci/docker.git
4.2 修改jenkins容器Dockerfile 1 2 3 4 5 6 7 cd ~/jenkins/jenkins/docker # jenkins的时区设置 sudo cp /usr/share/zoneinfo/Asia/Shanghai localtime echo 'Asia/Shanghai' > timezone # 使用root创建 sudo vi Dockerfile
需要修改的内容
第3行
1 2 3 4 5 6 7 RUN apt-get update && apt-get upgrade -y && apt-get install -y git curl && rm -rf /var/lib/apt/lists/* RUN echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main" >> /etc/apt/sources.list \ && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367 \ && apt-get update \ && apt-get install -y git curl ansible libltdl7 \ && rm -rf /var/lib/apt/lists/*
第36行
1 2 3 ARG TINI_VERSION=v0.16.1 # 修改为 ARG TINI_VERSION=v0.18.0
第47行
1 2 3 ENV JENKINS_VERSION ${JENKINS_VERSION:-2.176.2} # 修改为 ENV JENKINS_VERSION ${JENKINS_VERSION:-2.199}
第50行
1 2 3 JENKINS_SHA=33a6c3161cf8de9c8729fd83914d781319fd1569acf487c7b1121681dba190a5 # 修改为 JENKINS_SHA=e5095ae6f8ccf7ef4934d7745f2e086a2e9e2a42a0e6777f009d3e54c8404b96
第73行
1 2 3 4 5 6 7 # 注释 USER ${user} # 添加 USER root COPY localtime /etc/localtime COPY timezone /etc/timezone
完整的Dockerfile
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 FROM openjdk:8 -jdk-stretchRUN echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main" >> /etc/apt/sources.list \ && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367 \ && apt-get update \ && apt-get install -y git curl ansible libltdl7 \ && rm -rf /var/lib/apt/lists/* ARG user =jenkinsARG group=jenkinsARG uid=1000 ARG gid=1000 ARG http_port=8080 ARG agent_port=50000 ARG JENKINS_HOME=/var/jenkins_homeARG REF=/usr/share/jenkins/refENV JENKINS_HOME $JENKINS_HOMEENV JENKINS_SLAVE_AGENT_PORT ${agent_port}ENV REF $REFRUN mkdir -p $JENKINS_HOME \ && chown ${uid} :${gid} $JENKINS_HOME \ && groupadd -g ${gid} ${group} \ && useradd -d "$JENKINS_HOME " -u ${uid} -g ${gid} -m -s /bin/bash ${user} VOLUME $JENKINS_HOME RUN mkdir -p ${REF} /init.groovy.d ARG TINI_VERSION=v0.18.0 COPY tini_pub.gpg ${JENKINS_HOME} /tini_pub.gpg RUN curl -fsSL https://github.com/krallin/tini/releases/download/${TINI_VERSION} /tini-static-$(dpkg --print-architecture) -o /sbin/tini \ && curl -fsSL https://github.com/krallin/tini/releases/download/${TINI_VERSION} /tini-static-$(dpkg --print-architecture).asc -o /sbin/tini.asc \ && gpg --no-tty --import ${JENKINS_HOME} /tini_pub.gpg \ && gpg --verify /sbin/tini.asc \ && rm -rf /sbin/tini.asc /root/.gnupg \ && chmod +x /sbin/tini ARG JENKINS_VERSIONENV JENKINS_VERSION ${JENKINS_VERSION:-2.199 }ARG JENKINS_SHA=e5095ae6f8ccf7ef4934d7745f2e086a2e9e2a42a0e6777f009d3e54c8404b96ARG JENKINS_URL=https://repo.jenkins-ci.org/public/org/jenkins-ci/main/jenkins-war/${JENKINS_VERSION}/jenkins-war-${JENKINS_VERSION}.warRUN curl -fsSL ${JENKINS_URL} -o /usr/share/jenkins/jenkins.war \ && echo "${JENKINS_SHA} /usr/share/jenkins/jenkins.war" | sha256sum -c - ENV JENKINS_UC https://updates.jenkins.ioENV JENKINS_UC_EXPERIMENTAL=https://updates.jenkins.io/experimentalENV JENKINS_INCREMENTALS_REPO_MIRROR=https://repo.jenkins-ci.org/incrementalsRUN chown -R ${user} "$JENKINS_HOME " "$REF " EXPOSE ${http_port}EXPOSE ${agent_port}ENV COPY_REFERENCE_FILE_LOG $JENKINS_HOME/copy_reference_file.logUSER rootCOPY localtime /etc/localtime COPY timezone /etc/timezone COPY jenkins-support /usr/local/bin/jenkins-support COPY jenkins.sh /usr/local/bin/jenkins.sh COPY tini-shim.sh /bin/tini ENTRYPOINT ["/sbin/tini" , "--" , "/usr/local/bin/jenkins.sh" ] COPY plugins.sh /usr/local/bin/plugins.sh COPY install-plugins.sh /usr/local/bin/install-plugins.sh
构建jenkins docker镜像
1 sudo docker build -t jenkins:2.199 .
4.3 编写docker-compose.yml jenkins需要访问域名,需要设置dsn
文件存放路径/jenkins/jenkins
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 version: '3' services: jenkins: container_name: jenkins_inte image: jenkins:2.199 ports: - "8080:8080" volumes: - /var/jenkins_home:/var/jenkins_home - /usr/bin/make:/usr/bin/make - /usr/bin/docker:/usr/bin/docker - /var/run/docker.sock:/var/run/docker.sock restart: always dns: - 114.114 .114 .114 environment: - JAVA_OPTS="-Dorg.apache.commons.jelly.tags.fmt.timeZone=Asia/Shanghai" - JAVA_OPTS="-Duser.timezone=Asia/Shanghai" - JAVA_OPTS="-Dfile.encoding=UTF-8" networks: deploy: ipv4_address: 172.20 .0 .4 networks: deploy: external: true
启动jenkins docker容器
1 sudo docker-compose up -d
4.4 jenkins初始化 初始化需要时间比较长
密码:sudo cat /var/jenkins_home/secrets/initialAdminPassword
创建管理员账号
1 2 3 4 5 6 7 8 # 用户名 jenkins # 密码 wyy123456 # 全名 jenkins # 电子邮件地址 1368299513@qq.com
4.4.1 安装插件 安装go,ansiColor和ansible插件
重启jenkins:127.0.0.1:8080/restart
4.4.2 创建凭证
gogs访问账号
私有容器仓库访问账号
ansible凭证
4.4.2 全局工具配置
新增ansible配置
新增docker配置
sudo docker -v
新增go配置
1 2 3 4 5 6 7 8 9 10 11 12 # 手动下载golang sudo mkdir -p /var/jenkins/mytools cd /var/jenkins/mytools sudo wget https://studygolang.com/dl/golang/go1.13.1.linux-amd64.tar.gz sudo tar xvf go1.13.1.linux-amd64.tar.gz sudo mv go go1.13.1 # gopath sudo mkdir -p /var/jenkins/mytools/gopath sudo mkdir -p /var/jenkins/mytools/gopath/src sudo mkdir -p /var/jenkins/mytools/gopath/pkg sudo mkdir -p /var/jenkins/mytools/gopath/bin
4.4.3 SSH远程登录 如果要使用root用户远程登陆需要修改ssh配置文件(非root用户无需修改)
设置root用户密码sudo passwd root
编辑/etc/ssh/sshd_config
文件(没有这文件需要安装ssh:sudo apt install ssh
)
1 2 3 # 找到PermitRootLogin,注释掉这一行 # 添加PermitRootLogin yes ,保存,退出。 sudo service sshd restart
生成密钥
1 2 3 4 5 6 7 8 9 10 11 12 # 进入 jenkins 容器交互模式 sudo docker exec -it jenkins_inte bash # 生成 ssh 免密登入 密钥 mkdir -p /var/jenkins_home/ssh ssh-keygen -t rsa -C "1368299513@qq.com" -f /var/jenkins_home/ssh/jenkins_ansible # 复制公钥到远程免密登入的服务器上 ssh-copy-id -i /var/jenkins_home/ssh/jenkins_ansible.pub root@192.168.221.132 # 退出容器 exit
4.5 设置邮箱 注意需要设置dns,否则无法访问smtp.qq.com域名
4.5.1 jenkins自带邮箱设置
4.5.1 邮箱插件配置 首先要先安装Email Extension Plugin
设置发件人等信息
配置邮件内容模版
邮件内容模板
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 <!DOCTYPE html > <html > <head > <meta charset ="UTF-8" > <title > ${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title > </head > <body leftmargin ="8" marginwidth ="0" topmargin ="8" marginheight ="4" offset ="0" > <table class ="table" width ="1000" border ="1" cellspacing ="0" cellpadding ="5" > <caption align ="center" > <h3 > 项目构建信息</h3 > </caption > <thead > <tr > <th > 构建项目-<b > ${PROJECT_NAME}</b > </th > </tr > </thead > <tbody > <tr > <td > <font color ="#CC0000" > <b > 构建结果 - ${BUILD_STATUS}</b > </font > </td > </tr > <tr > <td > 测试数量-${TEST_COUNTS, var="total"}</td > </tr > </tbody > <tr > 本邮件由系统自动发出,无需回复!<br /> 各位同事,大家好,以下为${PROJECT_NAME}项目构建信息</br > </tr > <tr > <td > <br /> <b > <font color ="#0B610B" > 构建报告</font > </b > <hr size ="2" width ="100%" align ="center" /> <ul > <li > 构建报告:<a href ="${BUILD_URL}allure/" > ${PROJECT_URL}allure/</li > </ul > </td > </tr > <tr > <td > <br /> <b > <font color ="#0B610B" > 构建信息</font > </b > <hr size ="2" width ="100%" align ="center" /> <ul > <li > 项目名称: ${PROJECT_NAME}</li > <li > 构建编号: 第${BUILD_NUMBER}次构建</li > <li > 触发原因:${CAUSE}</li > <li > 构建状态:${BUILD_STATUS}</li > <li > 构建日志:<a href ="${BUILD_URL}console" > ${BUILD_URL}console</a > </li > <li > 构建 Url: <a href ="${BUILD_URL}" > ${BUILD_URL}</a > </li > <li > 工作目录: <a href ="${PROJECT_URL}ws" > ${PROJECT_URL}ws</a > </li > <li > 项目 Url: <a href ="${PROJECT_URL}" > ${PROJECT_URL}</a > </li > </ul > </td > </tr > <tr > <td > <b > <font color ="#0B610B" > 构建详细信息</font > </b > <hr size ="2" width ="100%" align ="center" /> <ul > <li > BRANCH_NAME: ${BRANCH_NAME}</li > <li > CHANGE_ID: ${CHANGE_ID}</li > <li > CHANGE_URL: ${CHANGE_URL}</li > <li > CHANGE_TITLE: ${CHANGE_TITLE}</li > <li > CHANGE_AUTHOR: ${CHANGE_AUTHOR}</li > <li > CHANGE_AUTHOR_DISPLAY_NAME: ${CHANGE_AUTHOR_DISPLAY_NAME}</li > <li > CHANGE_AUTHOR_EMAIL: ${CHANGE_AUTHOR_EMAIL}</li > <li > CHANGE_TARGET: ${CHANGE_TARGET}</li > <li > BUILD_NUMBER: ${BUILD_NUMBER}</li > <li > BUILD_DISPLAY_NAME: ${BUILD_DISPLAY_NAME}</li > <li > BUILD_ID: ${BUILD_ID}</li > <li > JOB_NAME: ${JOB_NAME}</li > <li > JOB_BASE_NAME: ${JOB_BASE_NAME}</li > <li > BUILD_TAG: ${BUILD_TAG}</li > <li > EXECUTOR_NUMBER: ${EXECUTOR_NUMBER}</li > <li > NODE_NAME: ${NODE_NAME}</li > <li > NODE_LABELS: ${NODE_LABELS}</li > <li > WORKSPACE: ${WORKSPACE}</li > <li > JENKINS_HOME: ${JENKINS_HOME}</li > <li > JENKINS_URL: ${JENKINS_URL}</li > <li > BUILD_URL: ${BUILD_URL}</li > <li > JOB_URL: ${JOB_URL}</li > <li > GIT_COMMIT: ${GIT_COMMIT}</li > <li > GIT_PREVIOUS_COMMIT: ${GIT_PREVIOUS_COMMIT}</li > <li > GIT_PREVIOUS_SUCCESSFUL_COMMIT: ${GIT_PREVIOUS_SUCCESSFUL_COMMIT}</li > <li > GIT_BRANCH: ${GIT_BRANCH}</li > <li > GIT_LOCAL_BRANCH: ${GIT_LOCAL_BRANCH}</li > <li > GIT_URL: ${GIT_URL}</li > <li > GIT_COMMITTER_NAME: ${GIT_COMMITTER_NAME}</li > <li > GIT_AUTHOR_NAME: ${GIT_AUTHOR_NAME}</li > <li > GIT_COMMITTER_EMAIL: ${GIT_COMMITTER_EMAIL}</li > <li > GIT_AUTHOR_EMAIL: ${GIT_AUTHOR_EMAIL}</li > <li > MERCURIAL_REVISION: ${MERCURIAL_REVISION}</li > <li > MERCURIAL_REVISION_SHORT: ${MERCURIAL_REVISION_SHORT}</li > <li > MERCURIAL_REVISION_NUMBER: ${MERCURIAL_REVISION_NUMBER}</li > <li > MERCURIAL_REVISION_BRANCH: ${MERCURIAL_REVISION_BRANCH}</li > <li > MERCURIAL_REPOSITORY_URL: ${MERCURIAL_REPOSITORY_URL}</li > <li > SVN_REVISION: ${SVN_REVISION}</li > <li > SVN_URL: ${SVN_URL}</li > </ul > </td > </tr > <tr > <td > <h4 > <font color ="#0B610B" > 失败用例</font > </h4 > ${FAILED_TESTS}<br /> </td > </tr > <tr > <td > <h4 > <font color ="#0B610B" > 最近提交(#$GIT_REVISION)</font > </h4 > </td > </tr > <tr > <td > <b > <font color ="#0B610B" > 变更信息:</font > </b > <hr size ="2" width ="100%" align ="center" /> </td > </tr > <tr > <td > <ul > <li > 上次构建成功后变化 : ${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="%c", changesFormat="<li > %d [%a] %m</li > "} </li > </ul > </td > </tr > <tr > <td > <ul > <li > 上次构建不稳定后变化 : ${CHANGES_SINCE_LAST_UNSTABLE, reverse=true, format="%c", changesFormat="<li > %d [%a] %m</li > "} </li > </ul > </td > <tr > <td > <ul > <li > 历史变更记录 : <a href ="${PROJECT_URL}changes" > ${PROJECT_URL}changes</a > </li > </ul > </td > </tr > <tr > <td > <ul > <li > 变更集:${JELLY_SCRIPT,template="html"}</li > </ul > </td > </tr > <tr > <td > <b > <font color ="#0B610B" > 构建日志 (最后 200行):</font > </b > <hr size ="2" width ="100%" align ="center" /> </td > </tr > <tr > <td > <textarea cols ="120" rows ="30" readonly ="readonly" style ="font-family: Courier New" > ${BUILD_LOG, maxLines=200}</textarea > </td > </tr > </table > </body > </html >
设置邮件触发机制
4.6 项目构建邮箱提醒 在项目配置中设置
4.6.1 使用自带邮箱提醒
4.6.2 使用邮箱插件(推荐) 使用插件可以自定义邮件内容,添加附件等功能,推荐使用
5.构建go运行alpine容器 编写Dockerfile文件,文件存放路径~/jenkins/alpine
1 2 3 4 5 6 7 8 9 10 11 12 13 FROM alpine:latestWORKDIR / RUN apk update \ && apk upgrade \ && apk --no-cache add bash ca-certificates libc6-compat tzdata \ && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo "Asia/Shanghai" > /etc/timezone \ && echo "hosts: files mdns4_minimal[NOTFOUND=return] dns mdns4" >> /etc/nsswitch.conf \ && rm -rf /var/cache/apk/* /tmp/*
构建镜像:sudo docker build -t 172.19.0.1/library/alpine-ca .
测试alpine-ca镜像
1 2 sudo docker run -it --rm 172.19.0.1/library/alpine-ca date # Mon Oct 14 21:15:37 CST 2019
推送镜像到私有仓库
1 2 3 # 先登陆仓库 sudo docker login -u admin -p 123456 172.19.0.1 sudo docker push 172.19.0.1/library/alpine-ca
6.测试环境编译部署 为微服务创建一个网络
1 2 3 4 5 # 创建 docker network create -d bridge --subnet=172.21.0.0/24 --gateway=172.21.0.1 microx_dev # 删除 docker network create microx_dev
任务命名规则:框架名-类型-服务-环境-本服务ip-配置中心ip
microx-srv-gconfig-dev-172.21.0.3-172.21.0.2
pipeline脚本
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 #!groovy timestamps { node { def GOROOT = tool 'GOROOT_1.13.1' def DOCKERROOT = tool name: 'DOCKER_19.03.2-ce' , type: 'org.jenkinsci.plugins.docker.commons.tools.DockerTool' env.PATH = "${GOROOT}/bin:${DOCKERROOT}:${env.PATH}" env.GOPATH = "/var/jenkins_home/mytools/gopath" env.GOPROXY = "https://goproxy.io" def String FIRST_NAME = "${JOB_NAME}" .split('-' )[0 ] def String MIDDLE_NAME = "${JOB_NAME}" .split('-' )[1 ] def String LAST_NAME = "${JOB_NAME}" .split('-' )[2 ] def String DEPLOY = "${JOB_NAME}" .split('-' )[3 ] def String SERVER_IP = "${JOB_NAME}" .split('-' )[4 ] def String GCONFIG_IP = "${JOB_NAME}" .split('-' )[5 ] env.DEPLOY_MOD = "${DEPLOY}" env.GCONFIG_ADDR = "${GCONFIG_IP}:9600" env.WORKPATH = "/var/jenkins_home/workspace/${JOB_NAME}" env.BUILDPATH = "${env.WORKPATH}/${MIDDLE_NAME}/${LAST_NAME}" def String BUILDPATH = "${env.BUILDPATH}" env.BINARYNAME = "${MIDDLE_NAME}-${LAST_NAME}" env.CONTAINERNAME = "${env.BINARYNAME}" env.DOCKERFILE = "${env.BUILDPATH}/Dockerfile" env.IMAGENAME = "${MIDDLE_NAME}-${LAST_NAME}-${DEPLOY}" def String MYCREDENTIALSID = "68f960c0-cf08-44af-a27b-3c658f73794c" def String MYREPOSITORYURL = "http://172.20.0.3:3000/jenkins/microx.git" def String ANSIBLECREID = "092d8e04-81fd-4081-b7a3-5de9b07a3166" def String PLAYBOOKPATH = "/var/jenkins_home/ansible" def String REGISTRYCREID = "0104b6b6-ae88-4fb3-9d65-42262bbce892" def String REGISTRYURL = "172.22.0.1" def String REGISTRYUSER="admin" def String REGISTRYPASS="123456" def String NAMESPACES = "library" def String IMGBRANCH = "latest" env.IMAGETAG = "${REGISTRYURL}/${NAMESPACES}/${env.IMAGENAME}:${IMGBRANCH}" sh "echo $PATH" sh "echo ${env.WORKPATH}" sh "echo ${BUILDPATH}" sh "echo ${env.BINARYNAME}" sh "echo ${FIRST_NAME}" sh "echo ${MIDDLE_NAME}" sh "echo ${LAST_NAME}" stage('拉取代码' ) { git credentialsId: "${MYCREDENTIALSID}" , url: "${MYREPOSITORYURL}" } stage('安装依赖' ) { echo "microx 不需要这个步骤!" } stage('删除容器' ) { echo "drop microx container" try { sh "docker rm -f ${env.CONTAINERNAME}" }catch (error){ echo error.getMessage() } try { sh "docker rmi ${env.IMAGETAG}" }catch (error){ echo error.getMessage() } } stage('编译构建' ) { echo "compile binary" try { sh'''#!/bin/bash -xe echo $SHELL echo $PATH go version go env cd ${BUILDPATH} env CGO_ENABLED=0 GOOS=linux go build -v -o ${BINARYNAME} ''' }catch (error){ echo error.getMessage() } def customImage = docker.build("${env.IMAGETAG}" , "-f ${env.DOCKERFILE} ${BUILDPATH}" ) docker.withRegistry("http://${REGISTRYURL}" , "${REGISTRYCREID}" ) { customImage.push() } } stage('部署容器' ) { echo "deploment microx service" sh "echo ${env.CONTAINERNAME}" sh "echo ${env.IMAGETAG}" sh "echo ${env.DEPLOY_MOD}" ansiColor('xterm' ) { ansiblePlaybook ( colorized: true , disableHostKeyChecking: true , credentialsId: "${ANSIBLECREID}" , installation: "ansible-playbook" , inventory: "${PLAYBOOKPATH}/hosts" , playbook: "${PLAYBOOKPATH}/deployment_microx_dev.yaml" , extras: "-v" , extraVars: [ CONTAINER_NAME: "${env.CONTAINERNAME}" , IMAGE_NAME: "${env.IMAGETAG}" , DEPLOY_MOD: "${env.DEPLOY_MOD}" , GCONFIG_ADDR: "${env.GCONFIG_ADDR}" , REGISTRY_USER: "${REGISTRYUSER}" , REGISTRY_PASS: "${REGISTRYPASS}" , REGISTRY_LINK: "${REGISTRYURL}" , SERVER_ADDR: "${SERVER_IP}" , ] ) } } } }
ansible hosts
mkdir /var/jenkins_home/ansible
vi /var/jenkins_home/ansible/hosts
1 2 [dev] dev1 ansible_ssh_host=192.168.221.132 ansible_ssh_port=22 ansible_ssh_private_key_file=/var/jenkins_home/ssh/jenkins_ansible
vi /var/jenkins_home/ansible/deployment_microx_dev.yaml
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 --- - hosts: dev vars: - BASE_PATH: /root/microx_dev tasks: - name: docker stop command: docker stop {{ CONTAINER_NAME }} ignore_errors: True tags: alldown - name: docker rm command: docker rm -f {{ CONTAINER_NAME }} ignore_errors: True tags: alldown - name: login to private docker registry command: docker login -u {{ REGISTRY_USER }} -p {{ REGISTRY_PASS }} {{ REGISTRY_LINK }} - name: docker pull image command: docker pull {{ IMAGE_NAME }} - name: check cid file shell: if [[ -f "{{ BASE_PATH }}/{{ CONTAINER_NAME }}/cid" ]]; then /bin/true; else /bin/false; fi register: result ignore_errors: True - command: mkdir -p {{ BASE_PATH }}/{{ CONTAINER_NAME }} when: result is failed - command: touch {{ BASE_PATH }}/{{ CONTAINER_NAME }}/cid when: result is failed - command: cat {{ BASE_PATH }}/{{ CONTAINER_NAME }}/cid when: result is success - name: docker up in the background # command: docker run -d --net didong_default --name {{ CONTAINER_NAME }} --link consul:consul -e MICRO_REGISTRY_ADDRESS=consul:8500 -v {{ BASE_PATH }}/{{ CONTAINER_NAME }}/cid:/cid -v {{ BASE_PATH }}/{{ CONTAINER_NAME }}/logs:/logs {{ IMAGE_NAME }} --config_address={{ GCONFIG_ADDR }} # command: docker run -d --net didong_default --name {{ CONTAINER_NAME }} -e MICRO_REGISTRY_ADDRESS=consul:8500 -v {{ BASE_PATH }}/{{ CONTAINER_NAME }}/cid:/cid -v {{ BASE_PATH }}/{{ CONTAINER_NAME }}/logs:/logs {{ IMAGE_NAME }} --config_address={{ GCONFIG_ADDR }} command: docker run -d --net microx_dev --ip {{ SERVER_ADDR }} --name {{ CONTAINER_NAME }} -e MICRO_REGISTRY_ADDRESS=consul:8500 -e MICROX_DEPLOY_ENV={{ DEPLOY_MOD }} -v {{ BASE_PATH }}/{{ CONTAINER_NAME }}/cid:/cid -v {{ BASE_PATH }}/{{ CONTAINER_NAME }}/logs:/logs {{ IMAGE_NAME }} --config_address={{ GCONFIG_ADDR }} - name: delete all unlabeled images shell: docker rmi -f `docker images -f dangling=true -q` ignore_errors: True - name: container status command: docker logs {{ CONTAINER_NAME }} register: psinfo tags: allstatus - name: display variable debug: var: psinfo.stdout verbosity: 0 tags: allstatus
7.正式环境编译部署 microx_srv-gconfig_prod
pipeline脚本
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 #!groovy timestamps { node { def GOROOT = tool 'GOROOT_1.13.1' def DOCKERROOT = tool name: 'DOCKER_19.03.2-ce' , type: 'org.jenkinsci.plugins.docker.commons.tools.DockerTool' env.PATH = "${GOROOT}/bin:${DOCKERROOT}:${env.PATH}" env.GOPATH = "/var/jenkins_home/mytools/gopath" env.GOPROXY = "https://goproxy.io" def String FIRST_NAME = "${JOB_NAME}" .split('_' )[0 ] def String MIDDLE_NAME = "${JOB_NAME}" .split('_' )[1 ].split('-' )[0 ] def String LAST_NAME = "${JOB_NAME}" .split('-' )[1 ].split('_' )[0 ] def String DEPLOY = "${JOB_NAME}" .split('-' )[1 ].split('_' )[1 ] env.DEPLOY_MOD = "${DEPLOY}" env.GCONFIG_ADDR = "gconfig:9600" env.WORKPATH = "/var/jenkins_home/workspace/${JOB_NAME}" env.BUILDPATH = "${env.WORKPATH}/${MIDDLE_NAME}/${LAST_NAME}" def String BUILDPATH = "${env.BUILDPATH}" env.BINARYNAME = "${MIDDLE_NAME}-${LAST_NAME}" env.CONTAINERNAME = "${env.BINARYNAME}" env.DOCKERFILE = "${env.BUILDPATH}/Dockerfile" env.IMAGENAME = "${JOB_NAME}" def String MYCREDENTIALSID = "b8ecc066-0f0b-4a05-b686-d42dff34cbb6" def String MYREPOSITORYURL = "http://172.18.0.3:3000/jenkins/microx.git" def String ANSIBLECREID = "092d8e04-81fd-4081-b7a3-5de9b07a3166" def String PLAYBOOKPATH = "/var/jenkins_home/ansible" def String REGISTRYCREID = "3fd1a3be-5378-4ee9-973a-9895433b4709" def String REGISTRYURL = "127.0.0.1:5000" def String IMGBRANCH = "latest" env.IMAGETAG = "${REGISTRYURL}/${env.IMAGENAME}:${IMGBRANCH}" def String BASE_PATH = "/root/microx_prod" sh "echo $PATH" sh "echo ${env.WORKPATH}" sh "echo ${BUILDPATH}" sh "echo ${env.BINARYNAME}" sh "echo ${FIRST_NAME}" sh "echo ${MIDDLE_NAME}" sh "echo ${LAST_NAME}" stage('拉取代码' ) { git credentialsId: "${MYCREDENTIALSID}" , url: "${MYREPOSITORYURL}" } stage('安装依赖' ) { echo "microx 不需要这个步骤!" } stage('删除容器' ) { echo "drop microx container" try { }catch (error){ echo error.getMessage() } try { }catch (error){ echo error.getMessage() } } stage('编译构建' ) { echo "compile binary" try { sh'''#!/bin/bash -xe echo $SHELL echo $PATH go version go env cd ${BUILDPATH} env CGO_ENABLED=0 GOOS=linux go build -v -o ${BINARYNAME} ''' }catch (error){ echo error.getMessage() } def customImage = docker.build("${env.IMAGETAG}" , "-f ${env.DOCKERFILE} ${BUILDPATH}" ) docker.withRegistry("http://${REGISTRYURL}" , "${REGISTRYCREID}" ) { customImage.push() } } stage('部署容器' ) { echo "deploment microx service" sh "echo ${env.CONTAINERNAME}" sh "echo ${env.IMAGETAG}" sh "echo ${env.DEPLOY_MOD}" ansiColor('xterm' ) { ansiblePlaybook ( colorized: true , disableHostKeyChecking: true , credentialsId: "${ANSIBLECREID}" , installation: "ansible-playbook" , inventory: "${PLAYBOOKPATH}/hosts" , playbook: "${PLAYBOOKPATH}/deployment_microx_prod.yaml" , extras: "-v" , extraVars: [ CONTAINER_NAME: "${env.CONTAINERNAME}" , IMAGE_NAME: "${env.IMAGETAG}" , DEPLOY_MOD: "${env.DEPLOY_MOD}" , GCONFIG_ADDR: "${env.GCONFIG_ADDR}" , DOCKER_COMPOSE_FILE: "${BASE_PATH}/${env.CONTAINERNAME}/docker-compose.yaml" ] ) } } } }
ansible hosts
vi /var/jenkins_home/ansible/hosts
1 2 [prod] prod1 ansible_ssh_host=192.168.23.144 ansible_ssh_port=22 ansible_ssh_private_key_file=/var/jenkins_home/ssh/jenkins_ansible
ansible deployment_microx_prod.yaml
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 --- - hosts: prod vars: - REGISTRY_USER: wyy - REGISTRY_PASS: 123456 - REGISTRY_LINK: 127.0.0.1:5000 - BASE_PATH: /root/microx_prod tasks: - name: docker-compose down all container command: docker-compose -f {{ DOCKER_COMPOSE_FILE }} down tags: alldown - name: Log in to private docker registry command: docker login -u {{ REGISTRY_USER }} -p {{ REGISTRY_PASS }} {{ REGISTRY_LINK }} - name: docker-compose pull all image command: docker-compose -f {{ DOCKER_COMPOSE_FILE }} pull - name: docker-compose up in the background command: docker-compose -f {{ DOCKER_COMPOSE_FILE }} up -d - name: docker-compose show container status command: docker-compose -f {{ DOCKER_COMPOSE_FILE }} ps register: psinfo tags: allstatus - name: display variable debug: var: psinfo.stdout verbosity: 0 tags: allstatus
8.远程触发项目构建 8.1 新建一个自由风格的软件项目
使用playbook
8.2 生成jenkins用户token
复制保存生成的token
8.2 gogs服务器上的microx项目配置webhook
jenkins用户名:wyy token:11d57202b53d688c12789e39c85e8883b5
http://wyy:11d57202b53d688c12789e39c85e8883b5@127.0.0.1:8080/job/microx/build?token=microx-token
测试推送是否触发
9.资料 客户端Jenkins自动构建指南
微信小程序集成 Jenkins