springboot
集成docker
實現自動化構建鏡像說明
-
文檔說明
該文檔僅包括通過配置springboot、docker、jenkins、git、appollo等實現持續構建,持續發布的功能,不包括各個組件使用細節的講解。
-
環境說明
name version desc spring boot 2.0.2.RELEASE spring boot docker 1.13.1 docker harbor 1.7.0 鏡像倉庫 jenkinsci/blueocean 1.9.0 jenkins的blueocean工具 maven 3-alpine maven gitlab 10.2.3 gitlab -
自動化構建的構想圖
-
springboot
配置文件- 包括測試服和正式服兩套服務,所以需要添加兩套配置文本
- 在
resources
下面添加application-test.properties
文本,內容同測試服的配置。 - 在
resources
下面添加application-prod.properties
文本,內容同slave10
的配置。 - 對於
test
和prod
的指定通過jvm
參數-Dspring.profiles.active=test
。
-
日志配置
- 日志文件保存地址統一為
/var/log/jenkinsci/zsm-eprofile/eprofile.2019-01-02.log
- 將鏡像的
/var/log/jenkinsci/zsm-eprofile
掛載到宿主機上對應的目錄/var/log/jenkinsci/zsm-eprofile
。這樣方便隨時對日志監控。 - 對
logback
配置示例<property name="LOG_HOME" value="/var/log/jenkinsci/zsm-eprofile/logs" />
- 日志文件保存地址統一為
-
pom
打包方式修改-
在
pom
的build
下面將打包方式修改為如下。<properties> <docker.image.prefix>bigdata-test.server.com</docker.image.prefix> </properties> <plugins> <!--這個插件是將所有的包打在一起--> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <!-- 這個插件主要是對打的包解壓到dependency目錄下 --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>unpack</id> <phase>package</phase> <goals> <goal>unpack</goal> </goals> <configuration> <artifactItems> <artifactItem> <groupId>${project.groupId}</groupId> <artifactId>${project.artifactId}</artifactId> <version>${project.version}</version> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> <!-- 根據 dockerfile 構建鏡像的mvn插件 --> <plugin> <groupId>com.spotify</groupId> <artifactId>dockerfile-maven-plugin</artifactId> <version>1.4.9</version> <configuration> <!-- 鏡像名 --> <repository>${docker.image.prefix}/${project.artifactId}</repository> <!-- tag:默認使用當前版本 --> <tag>${project.version}</tag> </configuration> </plugin> </plugins>
-
注意:如果在build標簽下面有下面的配置,需要刪除或者其他處理,要保證配置文件都能夠打包到jar里面
<resources> <resource> <directory>src/main/java</directory> <includes> <include>**/**</include> </includes> </resource> </resources>
-
-
在打包的
pom
文件同級目錄下創建Dockerfile
文件-
Dockerfile
內容##FROM指定依賴jdk8這個鏡像,VOLUME指定其掛載目錄 FROM openjdk:8-jdk-alpine VOLUME /tmp ##將dependency下面的內容拷貝到容器中 ARG DEPENDENCY=target/dependency COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib COPY ${DEPENDENCY}/META-INF /app/META-INF COPY ${DEPENDENCY}/BOOT-INF/classes /app ##容器啟動時通過PARAMS指定jvm參數 ENV PARAMS="" ## apk源 RUN data="" \ && sed -i 's/http:\/\/dl-cdn.alpinelinux.org\/alpine\//'"http:\/\/hub-mirror.c.163.com\/alpine\/"'/g' /etc/apk/repositories ## 字體包 RUN set -xe \ && apk --update add ttf-dejavu fontconfig ## 容器啟動時執行的命令 ENTRYPOINT ["sh","-c","java -cp app:app/lib/* $PARAMS com.zsm.test.Application"]
-
說明
上面是一種的構建鏡像的方式:這種方式是將jar解壓之后分別拷貝lib和class到容器中,這種方式能夠靈活的對歷史版本鏡像進行配置修改等操作,方便鏡像在不同服務器之間的遷移。還有另外一種,直接將整個jar拷貝到容器中:這種方式構建簡單,但是將配置打包到jar里面,不方便對配置的修改。
com.zsm.test.TestImageApplication
每個項目對應的主類不一樣,需要進行修改。
-
-
在打包的
pom
文件同級目錄下創建Jenkinsfile
-
Jenkinsfile
內容pipeline {
parameters {
booleanParam(name:'UPDATE_FORMUL', defaultValue:false,description:'默認false:不更新正式服; true:更新正式服')
booleanParam(name:'NOT_SKIP_BUILD', defaultValue:true, description:'默認true:構建新的鏡像;false:跳過鏡像構建')
}
environment {
BITBUCKET_COMMON_CREDS = credentials('docker-registry-up')
RegistryName = 'bigdata-test.server.com'
ImageName = 'test.zsm.com/enterprise-image'
ImageTag = '1.0.1'
}
agent any
stages {
stage('Build') {
when {
expression { return params.NOT_SKIP_BUILD }
}
agent {
docker {
image 'maven:3-alpine'
args '-v /root/.m2:/root/.m2'
}
}
steps {
echo '開始mvn構建鏡像...'
sh 'cd .'
sh 'mvn -B -DskipTests clean package dockerfile:build'
echo '鏡像構建完成!'
}
}
stage('Push') {
when {
expression { return params.NOT_SKIP_BUILD }
}
steps {
echo 'push鏡像到私有倉庫...'
sh 'docker login -u $BITBUCKET_COMMON_CREDS_USR -p $BITBUCKET_COMMON_CREDS_PSW $RegistryName'
sh 'docker tag $RegistryName/$ImageName:$ImageTag $RegistryName/$ImageName:latest'
sh 'docker push $RegistryName/$ImageName:$ImageTag'
sh 'docker push $RegistryName/$ImageName:latest'
sh 'docker rmi $RegistryName/$ImageName:$ImageTag'
sh 'docker rmi $RegistryName/$ImageName:latest'
echo 'push鏡像到私有倉庫完成!'
}
}
stage('Pull_Test') {
steps {
echo '開始更新測試服...'
sh 'ssh root@bigdata02 "/opt/server/zsm-microservice/jenkins-remote-shell/zsm-eprofile.sh"'
echo '測試服更新完成!'
}
}
stage('Pull_Formal') {
when {
expression { return params.UPDATE_FORMUL }
}
steps {
echo '開始更新正式服...'
sh 'ssh bigdata@10.0.100.154 "/opt/server/zsm-microservice/jenkins-remote-shell/zsm-eprofile.sh"'
echo '正式服更新完成!'
}
}
}
}
-
說明
- 這個文件對每次版本的變動都需要修改
ImageTag
為對應的版本。 - 注意:這個文件里面不能寫注釋。
- 對於在項目的
module
下打包的情況,需要把stage('Build')
下面的steps
里面的sh 'mvn -B -DskipTests clean package dockerfile:build -f pom.xml'
改為對應的module
下面。 Jenkins
的pipline
語法有Scripted Pipeline
和Declarative Pipeline
兩種,這里使用的是聲明式pipline
。pipline
語法詳情。
- 這個文件對每次版本的變動都需要修改
-
-
gitlab
項目設置- 添加為可訪問gitlab倉庫的賬號信息。
- 通過
setting
->members
->add member
的方式添加。
-
Jenkins
配置jenkins
訪問地址:http://192.168.1.100:8080
,賬號密碼:admin/123456
jenkins pipline
創建流程:new任務
->enter an item name
->流水線
->ok
.pipline
->definition
->pipline script from SCM
->SCM
->git
->Repository url
->credentials
->jenkins-gitlab-private
->輸入分支,默認master分支
->save
。- 如果
Jenkinsfile
在module
下面,請在Script Path
指定對應的path
-
遠端服務器腳本
-
因為鏡像的
pull
和run
都是通過Jenkins
調用遠程的shell
腳本來執行的,所以需要編寫對應的腳本。所以對於正式服和測試服的每一台服務器都需要對應的腳本。 -
腳本內容
#!/bin/bash docker login -u admin -p 123456 bigdata-test docker stop zsm-eprofile docker rm -f zsm-eprofile docker rmi bigdata-test.server.com/test.zsm.com/enterprise-image:latest docker pull bigdata-test.server.com/test.zsm.com/enterprise-image:latest docker run -d -p 9210:9210 -v /etc/hosts:/etc/hosts -v /var/log/jenkinsci/zsm-eprofile:/var/log/jenkinsci/zsm-eprofile --name zsm-eprofile -e PARAMS='-Dspring.profiles.active=test -Djava.security.egd=file:/dev/./urandom' --net=host bigdata-test.server.com/test.zsm.com/enterprise-image:latest
-
說明:
- 停止容器和刪除容器需要把名字和容器啟動的名字保持一致。
- 刪除鏡像和pull鏡像需要改為自己項目構建的鏡像,tag使用latest不變。
- 運行新的鏡像里面需要把
-v /var/log/jenkinsci/zsm-eprofile:/var/log/jenkinsci/zsm-eprofile
日志輸出改為自己項目對應的地址,--name zsm-eprofile
也需要改成自己項目的名字(和停止刪除容器的名字保持一致),-e PARAMS='-Dspring.profiles.active=test -Djava.security.egd=file:/dev/./urandom'
用來指定jvm
運行參數。
-
-
手動構建
Jenkins pipline
- 進入項目對應的任務,
立即構建
->build history
->查看構建日志
。
- 進入項目對應的任務,
-
不足
- 目前使用的是手動構建方式進行任務的啟動,后期優化成每一個項目都在git上有對應的生產分支,
jenkins
只需要webhook
對應的生產分支就行。 - 對於程序的版本和鏡像打包的tag,必須保持一致才能有效,版本的迭代每次需要改動兩個地方,有點麻煩。
- 目前使用的是手動構建方式進行任務的啟動,后期優化成每一個項目都在git上有對應的生產分支,
zsm_test_jenkins.sh 腳本
#!/bin/bash ssh root@bigdata01 "/opt/server/zsm-microservice/jenkins-remote-shell/zsm_test_jenkins.sh" sudo docker login -u admin -p 123456 bigdata-test sudo docker stop zsm_test_jenkins sudo docker rm -f zsm_test_jenkins sudo docker rmi bigdata-test.server.com/test.zsm.com/zsm_test_jenkins:latest sudo docker pull bigdata-test.server.com/test.zsm.com/zsm_test_jenkins:latest sudo docker run -d -p 9060:9060 -v /etc/hosts:/etc/hosts -v /var/log/jenkinsci/zsm_test_jenkins:/var/log/jenkinsci/zsm_test_jenkins --namezsm_test_jenkins -e PARAMS='-Dspring.profiles.active=test -Dapollo.configService=http://bigdata-test:8090 -Djava.security.egd=file:/dev/./urandom' --net=host bigdata-test.server.com/test.zsm.com/zsm_test_jenkins:latest