03-kubesphere流水线搭建
前言
及时清醒,事事甘心
9.流水线
参考:https://gitee.com/tanqidi/gulimall
9.1第一步gitee拉取代码
官方demo
地址:https://github.com/kubesphere/devops-java-sample/blob/master/Jenkinsfile-online
选择peng-mall-devops
,创建流水线
这里默认无需修改,点击创建
选择新建的流水线peng-mall-cicd
,选择编辑流水线
选择自定义流水线
选择node
,选择maven
添加步骤
新建码云凭证,我已经创建过了,自己输入自己的账号即可
添加步骤完成
选择编辑Jenkinsfile
,查看代码
pipeline {
agent {
node {
label 'maven'
}
}
stages {
stage('拉取代码') {
agent none
steps {
dir('code/peng-mall-parent') {
git(url: 'https://gitee.com/xxxxx/peng-mall.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false)
}
}
}
}
}
我这里因为项目代码有几层其他的目录,所以加了dir('code/peng-mall-parent'){}
命令,代表拉取code/peng-mall-parent
目录下的代码,没有别的目录层级的话删除即可
选择活动,选择运行,我这里已经运行成功了
点击运行记录进去,可以查看日志
9.2第一步-参数化构建&环境变量
9.2.1参数化构建
选择编辑Jenkinsfile
,添加版本号参数,默认为v0.0Beta
parameters {
string(name: 'PROJECT_VERSION', defaultValue: 'v0.0Beta', description: '')
}
选择编辑流水线,选择添加步骤,选择shell
,然后把PROJECT_VERSION
参数输出
echo $PROJECT_VERSION
选择编辑操作、编辑配置、添加参数、选项参数,添加PROJECT_NAME
参数,他的值是
gulimall-gateway
gulimall-auth-service
gulimall-cart
gulimall-coupon
gulimall-member
gulimall-order
gulimall-product
gulimall-search
gulimall-seckill
gulimall-third-party
gulimall-ware
代码
parameters {
string(name: 'PROJECT_VERSION', defaultValue: '1.0.0', description: '请输入版本号')
choice(name: 'PROJECT_NAME', choices: ['gulimall-gateway', 'gulimall-auth-service', 'gulimall-cart', 'gulimall-coupon', 'gulimall-member', 'gulimall-order', 'gulimall-product', 'gulimall-search', 'gulimall-seckill', 'gulimall-third-party', 'gulimall-ware'], description: '请选择服务名称')
}
选择运行
查看日志,变量已经成功输出
9.2.2环境变量
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITEE_CREDENTIAL_ID = 'gitee-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'docker.io'
DOCKERHUB_NAMESPACE = 'pengeng'
GITEE_ACCOUNT = '15549996135'
SONAR_CREDENTIAL_ID = 'sona-qube'
}
9.3第二步-Sonar代码质量分析
官方demo
全局配置文件:https://github.com/kubesphere/devops-java-sample/blob/master/configuration/settings.xml
完整配置见9.4
9.4第二步-Sonar代码质量分析&调试完成
9.4.1错误记录
参考:https://www.jianshu.com/p/bed574ae9ccc
查看jenkin
配置的sona
的token
是够正确
# curl -u YOUR_SONAR_TOKEN: "http://SONARQUBE_HOST/api/projects/search"
curl -u b36a45e8c313beb1c99b9924082deed039bf1861: "http://192.168.188.181:32467/api/projects/search"
查看sona
服务
kubectl get pod -n kubesphere-devops-system
查看jenkins
地址:http://192.168.188.181:30180/sonarqube-webhook/
export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services ks-jenkins)
export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services ks-jenkins)
export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT/sonarqube-webhook/
查看sonaqube
地址:http://192.168.188.181:30180
export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services sonarqube-sonarqube)
export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
Checking status of SonarQube task 'AZJJSjLVHdLHyflgZstE' on server 'sonar' java.lang.IllegalStateException: Unable to parse response from http://192.168.188.181:32467//api/ce/task?id=AZJJSjLVHdLHyflgZstE:
请求http://192.168.188.181:32467//api/ce/task?id=AZJJSjLVHdLHyflgZstE
返回的是个html
,不是json
结果,是我jenkins
地址配置错误,多个'/'
9.4.2配置
pom.xml
的sona
配置
https://github.com/kubesphere/devops-java-sample/blob/master/pom.xml
<sonar.jacoco.reportPaths>${PWD}/./target/jacoco.exec</sonar.jacoco.reportPaths>
<sonar.groovy.binaries>target/classes</sonar.groovy.binaries>
还有下面打包的部分
下面是完整配置
Jenkinsfile
pipeline {
agent {
node {
label 'maven'
}
}
parameters {
string(name: 'PROJECT_VERSION', defaultValue: '1.0.0', description: '请输入版本号')
choice(name: 'PROJECT_NAME', choices: ['gulimall-cart', 'gulimall-coupon', 'gulimall-member'], description: '请选择服务名称')
}
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITEE_CREDENTIAL_ID = 'gitee-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'docker.io'
DOCKERHUB_NAMESPACE = 'pengeng'
GITEE_ACCOUNT = '15549996135'
SONAR_CREDENTIAL_ID = 'sonar-token'
BRANCH_NAME = 'master'
}
stages {
stage('拉取代码') {
agent none
steps {
git(url: 'https://gitee.com/peng_p/peng-mall.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false)
dir('code/peng-mall-parent') {
sh 'echo 正在构建:$PROJECT_NAME 版本号:$PROJECT_VERSION 将会提交给 $REGISTRY 镜像仓库'
container('maven') {
sh "echo 当前目录:`pwd`"
sh 'ls -al `pwd`'
sh "mvn clean install -U -Dmaven.test.skip=true -e -X -gs `pwd`/mvn-settings.xml"
}
}
}
}
stage('SonarQube 分析') {
steps {
dir('code/peng-mall-parent') {
container('maven') {
withCredentials([string(credentialsId: "$SONAR_CREDENTIAL_ID", variable: 'SONAR_TOKEN')]) {
withSonarQubeEnv("sonar") {
sh "echo 当前目录:`pwd`"
// sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.branch=$BRANCH_NAME -Dsonar.login=$SONAR_TOKEN"
sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.login=$SONAR_TOKEN"
}
}
}
}
}
}
stage('阈值判断') {
steps {
script {
timeout(time: 1, unit: "HOURS") {
def qualityGate = waitForQualityGate()
if (qualityGate.status != 'OK') {
error "SonarQube 检测不通过: ${qualityGate.status}"
}
}
}
}
}
}
}
mvn-settings.xml
<settings>
<mirrors>
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
</settings>
pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<sonar.jacoco.reportPaths>${PWD}/./target/jacoco.exec</sonar.jacoco.reportPaths>
<sonar.groovy.binaries>target/classes</sonar.groovy.binaries>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.2</version>
<configuration>
<append>true</append>
</configuration>
<executions>
<execution>
<id>agent-for-ut</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>agent-for-it</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
<!-- 跳过单元测试 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.6.0.1398</version>
</plugin>
</plugins>
</build>
总算成功了
代码质量
9.5第三步-构建&推送镜像
9.5.1错误记录
java:8环境无法拉取
可以使用openjdk:8-jdk-alpine
版本的镜像
但在 openjdk:8-jdk-alpine
镜像中,默认没有安装 bash
,只有 sh
。因此,bash -c 'touch /app.jar'
这条命令会失败。
你可以将 Dockerfile
中的 RUN bash -c 'touch /app.jar'
替换为 RUN touch /app.jar
,这样可以直接使用 sh
来执行。
这里测试我只改了gulimall-cart/Dockerfile
,后面所有服务都需要修改
FROM openjdk:8-jdk-alpine
EXPOSE 8080
VOLUME /tmp
ADD target/*.jar /app.jar
# RUN bash -c 'touch /app.jar'
# 使用 sh 替代 bash
RUN touch /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar", "--spring.profiles.active=prod"]
无法将镜像上传到docker hub
因为国内docker老是被墙(docker hub也保留,后面有机会再调通),所以这次上传到阿里云,因为流程都是一样的,只是配置一下阿里云的凭证和相关命令
阿里云配置见9.5.2
9.5.2配置阿里云镜像仓库
参考:https://www.cnblogs.com/makalochen/p/14240796.html
官方地址:https://cr.console.aliyun.com/cn-shanghai/instance/repositories
创建本地仓库
本地仓库创建完成
我们需要留意docker login
、docker pull
、docker push
三条命令
需要留意自己的请求地址、命名空间、仓库名称、账号名称
9.5.3流水线配置阿里云
创建阿里云账号凭证,需要输入自己阿里云的账号密码
在环境变量添加自己阿里云的相关参数,分别是凭证(配置阿里云的账号密码)、请求地址、命名空间、仓库名称、账号名称
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITEE_CREDENTIAL_ID = 'gitee-id'
KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
REGISTRY = 'docker.io'
DOCKERHUB_NAMESPACE = 'pengeng'
GITEE_ACCOUNT = '15549996135'
SONAR_CREDENTIAL_ID = 'sonar-token'
BRANCH_NAME = 'master'
ALIYUN_CREDENTIAL_ID = 'aliyun-id'
ALIYUN_URL = 'crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com'
ALIYUN_NAMESPACE = 'pengpeng-namespace'
ALIYUN_ACCOUNT = 'pengpengservice'
}
创建阿里云的步骤,login
和push
地址拼对即可,tag
版本号可以小点
stage ('构建镜像-推送阿里云') {
steps {
dir('code/peng-mall-parent') {
container ('maven') {
sh 'cd service/$PROJECT_NAME && docker build -f Dockerfile -t $BRANCH_NAME-$BUILD_NUMBER .'
sh "echo 镜像:$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER"
sh 'docker images'
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$ALIYUN_CREDENTIAL_ID")]) {
sh 'echo "$DOCKER_PASSWORD" | docker login --username="$ALIYUN_ACCOUNT" "$ALIYUN_URL" --password-stdin'
sh 'docker tag $BRANCH_NAME-$BUILD_NUMBER $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER'
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER'
}
}
}
}
}
步骤都是成功状态
push
完成
9.5.4配置docker-hub
地址:https://github.com/kubesphere/devops-java-sample/blob/master/Jenkinsfile-online
需要修改的地方
代码
stage ('构建镜像-推送镜像') {
steps {
dir('code/peng-mall-parent') {
container ('maven') {
sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'
sh 'ls -al `pwd`'
sh 'cd service/$PROJECT_NAME && docker build -f Dockerfile -t $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$DOCKER_CREDENTIAL_ID", )]) {
sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'
sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER'
}
}
}
}
}
查看自己能否正常登录docker hub
因为老是登不上,所以选择了上传阿里云
echo "YOUR_PASSWORD" | docker login --username YOUR_USERNAME --password-stdin
9.6第四步-流水线编写完成
- 构建镜像 & 推送快照镜像
- 推送最新镜像
- 部署到开发集群环境
- 发布版本
stage ('构建镜像 & 推送快照镜像') {
steps {
dir('code/peng-mall-parent') {
container ('maven') {
sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'
sh 'cd service/$PROJECT_NAME && docker build -f Dockerfile -t $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'
sh "echo 快照镜像:$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER"
sh 'docker images'
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$ALIYUN_CREDENTIAL_ID")]) {
sh 'echo "$DOCKER_PASSWORD" | docker login --username="$ALIYUN_ACCOUNT" "$ALIYUN_URL" --password-stdin'
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER'
}
}
}
}
}
stage('推送最新镜像'){
steps{
dir('code/peng-mall-parent') {
container ('maven') {
sh 'docker tag $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:latest '
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:latest '
}
}
}
}
stage('部署到开发集群环境') {
steps {
dir('code/peng-mall-parent') {
input(id: "deploy-to-prod-$PROJECT_NAME", message: "是否将 $PROJECT_NAME 部署到开发集群环境?")
kubernetesDeploy(configs: "service/$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}
}
stage('发布版本'){
when{
expression{
return params.PROJECT_VERSION =~ /v.*/
}
}
steps {
container ('maven') {
input(id: 'release-image-with-tag', message: '是否发布当前版本?')
sh 'docker tag $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION '
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION '
withCredentials([usernamePassword(credentialsId: "$GITEE_CREDENTIAL_ID",
passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
sh 'git config --global user.email "pengpeng6135@163.com" '
sh 'git config --global user.name "peng" '
sh 'git tag -a $PROJECT_NAME-$PROJECT_VERSION -m "$PROJECT_VERSION" '
// https://gitee.com/peng_p/peng-mall.git
sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@gitee.com/$GITEE_NAME/peng-mall.git --tags --ipv4'
}
}
}
}
修改每个服务k8s
配置的镜像地址
9.7部署-移植数据库
创建mysql8
的工作负载
选择指定工作负载吗,选择mysql8
,暴露3302
端口
选择外网访问,选择NodePort
,选择开启会话保持
使用数据库连接工具,连接mysql8-node-port
把之前的数据全部导出来
新建数据库
把所有数据到入到k8s
的数据库里
9.8流水线细节优化&解决OOM
重新创建一个流水线
peng-mall-jenkinsfile-cicd
选择代码仓库,这里选择Git
高级设置
如何Jenkinsfile
不在根目录,可以指定位置
code/peng-mall-parent/Jenkinsfile
如果一开始运行没有选择分支、版本、项目名称,可以刷新,或者停止运行重新运行,要不然Jenkinsfile
获取不到PROJECT_NAME
项目名称
在Jenkinsfile
中配置所有服务,数组第一个就是默认值
parameters {
choice(name: 'PROJECT_NAME', choices: ['gulimall-gateway', 'gulimall-auth-service', 'gulimall-cart', 'gulimall-coupon', 'gulimall-member', 'gulimall-order', 'gulimall-product', 'gulimall-search', 'gulimall-seckill', 'gulimall-third-party', 'gulimall-ware'], description: '请选择服务名称')
}
需要配置gulimall-gateway
的镜像地址和端口
镜像地址是阿里云镜像地址,KubeSphere
的端口号范围是 30000 到 32767
容器OOMKilled
,说明容器部署异常,内存溢出
原因:jvm
启动的时候,分配内存过大,而k8s
里面部署的限制是500Mi【xx-deploy.yaml】
,导致内存溢出直接将pod
给杀
解决:构建docker
镜像的时候,约束微服务jvm
最大占用内存
配置gulimall-gateway
的Dockerfile
除了gulimall-gateway
网关服务,剩下的服务都在service
文件夹里面,所以这里加了一个判断
k8s
配置这里也需要根据服务判断路径
9.9流水线部署所有微服务
完整Jenkinsfile
pipeline {
agent {
node {
label 'maven'
}
}
parameters {
string(name: 'PROJECT_VERSION', defaultValue: '1.0', description: '请输入版本号')
choice(name: 'PROJECT_NAME', choices: ['gulimall-gateway', 'gulimall-auth-service', 'gulimall-cart', 'gulimall-coupon', 'gulimall-member', 'gulimall-order', 'gulimall-product', 'gulimall-search', 'gulimall-seckill', 'gulimall-third-party', 'gulimall-ware'], description: '请选择服务名称')
}
environment {
DOCKER_CREDENTIAL_ID = 'dockerhub-id'
GITEE_CREDENTIAL_ID = 'gitee-id'
KUBECONFIG_CREDENTIAL_ID = 'peng-mall-kubeconfig'
REGISTRY = 'docker.io'
DOCKERHUB_NAMESPACE = 'pengeng'
GITEE_ACCOUNT = '15549996135'
GITEE_NAME = 'peng_p'
SONAR_CREDENTIAL_ID = 'sonar-token'
BRANCH_NAME = 'master'
ALIYUN_CREDENTIAL_ID = 'aliyun-id'
ALIYUN_URL = 'crpi-e3iemos7j8ulr18e.cn-shanghai.personal.cr.aliyuncs.com'
ALIYUN_NAMESPACE = 'pengpeng-namespace'
ALIYUN_ACCOUNT = 'pengpengservice'
}
stages {
stage('拉取代码') {
agent none
steps {
git(url: 'https://gitee.com/peng_p/peng-mall.git', credentialsId: 'gitee-id', branch: 'master', changelog: true, poll: false)
dir('code/peng-mall-parent') {
sh 'echo 正在构建:$PROJECT_NAME 版本号:$PROJECT_VERSION 将会提交给 $REGISTRY 镜像仓库'
container('maven') {
sh "echo 当前目录:`pwd`"
sh 'ls -al `pwd`'
sh "mvn clean install -U -Dmaven.test.skip=true -e -X -gs `pwd`/mvn-settings.xml"
}
}
}
}
stage('SonarQube 分析') {
steps {
dir('code/peng-mall-parent') {
container('maven') {
withCredentials([string(credentialsId: "$SONAR_CREDENTIAL_ID", variable: 'SONAR_TOKEN')]) {
withSonarQubeEnv("sonar") {
sh "echo 当前目录:`pwd`"
// sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.branch=$BRANCH_NAME -Dsonar.login=$SONAR_TOKEN"
sh "mvn sonar:sonar -gs `pwd`/mvn-settings.xml -Dsonar.login=$SONAR_TOKEN"
}
}
}
}
}
}
stage('阈值判断') {
steps {
script {
timeout(time: 1, unit: "HOURS") {
def qualityGate = waitForQualityGate()
if (qualityGate.status != 'OK') {
error "SonarQube 检测不通过: ${qualityGate.status}"
}
}
}
}
}
//stage ('构建镜像-推送镜像') {
// steps {
// dir('code/peng-mall-parent') {
// container ('maven') {
// sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'
// sh 'ls -al `pwd`'
// sh 'cd service/$PROJECT_NAME && docker build -f Dockerfile -t $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'
//
// withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$DOCKER_CREDENTIAL_ID", )]) {
// sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'
// sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER'
// }
// }
// }
// }
//}
stage ('构建镜像 & 推送快照镜像') {
steps {
dir('code/peng-mall-parent') {
container ('maven') {
sh 'mvn -Dmaven.test.skip=true -gs `pwd`/mvn-settings.xml clean package'
sh """
if [ "$PROJECT_NAME" = "gulimall-gateway" ]; then
cd $PROJECT_NAME && docker build -f Dockerfile -t "$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER" .
else
cd service/$PROJECT_NAME && docker build -f Dockerfile -t "$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER" .
fi
"""
// sh 'cd service/$PROJECT_NAME && docker build -f Dockerfile -t $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER .'
sh "echo 快照镜像:$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER"
sh 'docker images'
withCredentials([usernamePassword(passwordVariable : 'DOCKER_PASSWORD', usernameVariable : 'DOCKER_USERNAME', credentialsId : "$ALIYUN_CREDENTIAL_ID")]) {
sh 'echo "$DOCKER_PASSWORD" | docker login --username="$ALIYUN_ACCOUNT" "$ALIYUN_URL" --password-stdin'
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER'
}
}
}
}
}
stage('推送最新镜像'){
steps{
dir('code/peng-mall-parent') {
container ('maven') {
sh 'docker tag $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:latest '
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:latest '
}
}
}
}
stage('部署到开发集群环境') {
steps {
dir('code/peng-mall-parent') {
input(id: "deploy-to-prod-$PROJECT_NAME", message: "是否将 $PROJECT_NAME 部署到开发集群环境?")
// kubernetesDeploy(configs: "service/$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
script {
if (PROJECT_NAME == "gulimall-gateway") {
kubernetesDeploy(configs: "$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
} else {
kubernetesDeploy(configs: "service/$PROJECT_NAME/deploy/**", enableConfigSubstitution: true, kubeconfigId: "$KUBECONFIG_CREDENTIAL_ID")
}
}
}
}
}
stage('发布版本'){
when{
expression{
return params.PROJECT_VERSION =~ /v.*/
}
}
steps {
container ('maven') {
input(id: 'release-image-with-tag', message: '是否发布当前版本?')
sh 'docker tag $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:SNAPSHOT-$BRANCH_NAME-$BUILD_NUMBER $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION '
sh 'docker push $ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:$PROJECT_VERSION '
withCredentials([usernamePassword(credentialsId: "$GITEE_CREDENTIAL_ID",
passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
sh 'git config --global user.email "pengpeng6135@163.com" '
sh 'git config --global user.name "peng" '
sh 'git tag -a $PROJECT_NAME-$PROJECT_VERSION -m "$PROJECT_VERSION" '
sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@gitee.com/$GITEE_NAME/peng-mall.git --tags --ipv4'
}
}
}
}
}
}
所有项目的Dockerfile
是一样的
FROM openjdk:8-jdk-alpine
EXPOSE 8080
VOLUME /tmp
ADD target/*.jar /app.jar
# RUN bash -c 'touch /app.jar'
# 使用 sh 替代 bash
RUN touch /app.jar
ENTRYPOINT ["java", "-jar", "-Xms128m", "-Xmx300m", "/app.jar", "--spring.profiles.active=prod"]
【xx-deploy.yaml】
需要修改镜像地址
镜像地址固定的,打包的时候就是发布最新的
$ALIYUN_URL/$ALIYUN_NAMESPACE/$PROJECT_NAME:latest
端口号范围必须是 30000 到 32767,我这里都是31000-31019
创作不易,感谢支持。