本文将从零开始教你搭建一个实用的自动发布流程,文中相关示例代码已上传到 github仓库 需要的朋友可以自取~
$ vi /etc/yum.repos.d/docker.repo
--- // 填入以下内容
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
---
$ sudo yum install -y docker-engine
$ sudo systemctl enable docker.service
$ sudo systemctl start docker
$ docker -v
1. mkdir /var/jenkins_home
2. sudo chown -R 1000:1000 /var/jenkins_home // 开放权限
3. sudo docker run -d -u root -name jenkins -p 8080:8080 -v /var/jenkins_home:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/bin/docker jenkinsci/blueocean
注意: 在启动Jenkins服务时要加上-v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/bin/docker,让我们可以在docker容器中使用外部docker (docker in docker)
当在jenkins启动成功后 浏览 http://localhost:8080 并等待 Unlock Jenkins 页面出现。
在命令行中输入docker logs jenkins, 复制自动生成的字母数字密码(在两组星号之间)。 在 Unlock Jenkins 页面, 粘贴该密码到 Administrator password 字段并点击 Continue。
选择install suggested pulgins 等待安装成功
创建用户,进入主页。
FROM node:9.6.0
RUN apt-get update
RUN apt-get install vim -y
RUN npm install -g pm2 --registry=https://registry.npm.taobao.org
ARG PRO_ENV=test # 接受运行参数
ENV PRO_ENV=$PRO_ENV
COPY ./ /demo
WORKDIR /demo
RUN /bin/bash scripts/build.sh
CMD /bin/bash scripts/start.sh
将账号密码配置在jenkins凭据中
{
"version": "1.0.0",
"registryName": "ccr.ccs.tencentyun.com/yohann/demo",
"env": {
"test": {
"credentialsId": "ssh-test”,
"host": "123.206.25.28"
},
"pro": {
"credentialsId": "ssh-test",
"host": "123.206.25.28"
}
}
}
避免在代码中写入账号密码,我们在Jenkins中配置相关凭据:
流水线语法支持两种格式:
1. 声明式流水线
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
2.脚本化流水线
node {
stage('Example') {
if (env.BRANCH_NAME == 'master') {
echo 'I only execute on the master branch'
} else {
echo 'I execute elsewhere'
}
}
}
脚本化的流水线自由度更高,因此我们选择脚本的写法
完整代码如下
import groovy.json.JsonSlurper
node {
currentBuild.result = “SUCCESS”
echo “PWD: ${pwd()}”
// 判断发布环境
if (env.BRANCH_NAME == 'release') {
env.PRO_ENV = "pro"
} else {
env.PRO_ENV = "test"
}
// 默认设置
env.VERSION = '1.0.0'
env.credentialsId = ''
env.host = ''
env.registryName = ''
def imageName = ''
def input_result // 用户输入项
try {
stage('config') {
echo "Branch: ${env.BRANCH_NAME}, Environment: ${env.PRO_ENV}"
input_result = input message: 'Check Tasks', ok: 'ok', parameters: [
booleanParam(name: 'install', defaultValue: false),
booleanParam(name: 'test', defaultValue: true),
booleanParam(name: 'deploy', defaultValue: true)
]
}
stage('Checkout'){
// 重置本地修改项
try {
sh 'git checkout .'
} catch (err) {
}
checkout scm
// 读取配置信息
if(fileExists('config.json')) {
def str = readFile 'config.json'
def jsonSlurper = new JsonSlurper()
def obj = jsonSlurper.parseText(str)
env.registryName = obj.registryName
def envConifg = obj.env[env.PRO_ENV]
echo "envConifg: ${envConifg}"
env.VERSION = obj.version
env.credentialsId = envConifg.credentialsId
env.host = envConifg.host
imageName = "${env.registryName}:${env.VERSION}_${env.PRO_ENV}_${BUILD_NUMBER}"
echo "VERSION: ${env.VERSION} ${imageName}"
}
sh 'ls'
}
stage('Install'){
if(input_result.install) {
docker.image('node:9.6.0').inside {
sh 'node -v'
sh 'sh ./scripts/install.sh'
}
}
}
stage('Test'){
if(input_result.test) {
docker.image('node:9.6.0').inside {
sh 'sh ./scripts/test.sh'
}
}
}
stage('Build Docker'){
// 构建上传镜像到容器仓库
if(input_result.deploy) {
def customImage = docker.build(imageName, "--build-arg PRO_ENV=${env.PRO_ENV} .")
docker.withRegistry("https://${env.registryName}", 'docker-demo') {
/* Push the container to the custom Registry */
customImage.push()
}
}
}
stage('Deploy'){
if(input_result.deploy) {
// wechat服务器
withCredentials([usernamePassword(credentialsId: env.credentialsId, usernameVariable: 'USER', passwordVariable: 'PWD')]) {
def otherArgs = '-p 8001:8001' // 区分不同环境的启动参数
def remote = [:]
remote.name = 'ssh-deploy'
remote.allowAnyHosts = true
remote.host = env.host
remote.user = USER
remote.password = PWD
if(env.PRO_ENV == "pro") {
otherArgs = '-p 3000:3000'
}
try {
sshCommand remote: remote, command: "docker rm -f demo"
} catch (err) {
}
sshCommand remote: remote, command: "docker run -d --name demo -v /etc/localtime:/etc/localtime -e PRO_ENV='${env.PRO_ENV}' ${otherArgs} ${imageName}"
}
// 删除旧的镜像
sh "docker rmi -f ${imageName.replaceAll("_${BUILD_NUMBER}", "_${BUILD_NUMBER - 1}")}"
}
}
}
catch (err) {
currentBuild.result = "FAILURE"
throw err
}
}
在git仓库中提交代码到release-test分支
在jenkins中打开blue-ocean执行该分支
本项目中的示例代码已上传到 github仓库 需要的朋友可以自取~