properties([ parameters([ [$class: 'ChoiceParameter', choiceType: 'PT_SINGLE_SELECT', description: '选择要部署 API or UI', name: 'modulePrefix', randomName: 'choice-parameter-5631314439613978', script: [ $class: 'GroovyScript', fallbackScript: [ classpath: [], sandbox: true, script: 'return[\'Could not get Env\']' ], script: [ classpath: [], sandbox: true, script: 'return["java","ui"]' ] ] ], [$class: 'CascadeChoiceParameter', choiceType: 'PT_SINGLE_SELECT', description: '选择要部署的项目', name: 'module', randomName: 'choice-parameter-5631314456178619', referencedParameters: 'modulePrefix', script: [ $class: 'GroovyScript', fallbackScript: [ classpath: [], sandbox: true, script: 'return[\'Could not get Environment from Env Param\']' ], script: [ classpath: [], sandbox: true, script: ''' if (modulePrefix.equals("java")){ return["storlead-centre-api"] } else if(modulePrefix.equals("ui")){ return["sp-user-center"] } ''' ] ] ] ]) ]) pipeline { options { timestamps() } environment { GROUPID = readMavenPom().getGroupId()//com.storlead ARTIFACTID = readMavenPom().getArtifactId()//sp-project VERSION = readMavenPom().getVersion()//1.0 } // 参数 parameters { choice( name: 'profile', choices: ['test', 'prod','uat'], description: '选择要部署的配置文件' ) } agent any stages { stage('处理参数') { steps { script { echo "处理参数" script { //服务器配置 MODULE_PREFIX = "${params.modulePrefix}" SERVER_SSH_PORT = 53023 SERVER_HOST = "node1.storlead.com" SWARM_INIT_REPLICAS_NUM = 1 //服务配置 API_PORT = 9200 API_REMOTE_DEBUG_PORT = 9201 API_NAMESPACE_RESTFUL = "${params.module}" //DOCKER配置 DOCKER_REGISTRY = "reg-aliyun" DOCKER_HOST = "registry.cn-shenzhen.aliyuncs.com" //Docker私服登陆url https://registry-vpc.cn-shenzhen.aliyuncs.com DOCKER_LOGIN_REGISTRY = "https://${DOCKER_HOST}" BUILD_PREFIX = "storlead-huawei" //镜像完整名称 registry-vpc.cn-shenzhen.aliyuncs.com/storlead/sp-project-management-prod:1.0 DOCKER_IMG_NAME = "${DOCKER_HOST}/${BUILD_PREFIX}/${params.module}-${params.profile}:${VERSION}" //镜像名 storlead/sp-project-management-prod:1.0 IMG_NAME = "${BUILD_PREFIX}/${params.module}-${params.profile}:${VERSION}" PUSH_DOCK_IMG = true SERVER_HOST_NAME = "test1" echo "为指定 module 设定对应 服务器及端口" echo "处理 ${params.module} 项目" if (params.modulePrefix == "java") { echo "---- storelad-centre-api" script { if (params.profile == "test") { SWARM_INIT_REPLICAS_NUM = 1 SERVER_HOST = "test1.storlead.com" API_PORT = 10060 API_REMOTE_DEBUG_PORT = 10061 SERVER_HOST_NAME = "test1" } else if (params.profile == "prod") { SERVER_HOST = "110.41.82.21" API_PORT = 10060 API_REMOTE_DEBUG_PORT = 10061 SERVER_HOST_NAME = "node1" } } } else if (params.modulePrefix == "ui") { script { if (params.profile == "test") { SERVER_HOST = "test1.storlead.com" } else if (params.profile == "prod") { SERVER_HOST = "110.41.82.21" } } } echo "处理MODULE_NAMESPACE_RESTFUL" //把 module 名 从 sp-xxx 变成 xxx 也就是 项目 的 namespace if (API_NAMESPACE_RESTFUL == "storlead-centre-api") { API_NAMESPACE_RESTFUL = "api" } echo "处理镜像推送" } } } } stage('Node 编译') { when { environment name: 'modulePrefix', value: 'ui' } agent { docker { // image "registry-vpc.cn-shenzhen.aliyuncs.com/storlead/node:19-alpine" image "node:20-alpine" args '-v /app:/app/:z -v /etc/localtime:/etc/localtime:ro -u root' reuseNode true } } steps { withCredentials([ usernamePassword(credentialsId: 'storleadHW', usernameVariable: 'usernameHW', passwordVariable: 'passwordHW'), usernamePassword(credentialsId: 'storlead', usernameVariable: 'username', passwordVariable: 'password') ]) { script { echo "发布 UI 代码" def remote = [:] remote.allowAnyHosts = true remote.name = "${SERVER_HOST}" remote.host = "${SERVER_HOST}" remote.port = 53023 remote.user = username remote.password = password if (params.profile == "prod") { remote.port = 22 remote.user = "root" remote.user = usernameHW remote.password = passwordHW } if(params.module == 'sp-user-mobile-center') { sh """cd ${params.modulePrefix}/${params.module} && npm install && npm run build:${params.profile}""" } else { sh """cd ${params.modulePrefix}/${params.module} && npm install && npm run ${params.profile}""" } // sh """cd ${params.modulePrefix}/${params.module} && npm run ${params.profile}""" sshCommand remote: remote, command: "mkdir -p /app/sp/ui/app-centre/${params.profile}/${params.module}" sshCommand remote: remote, command: "rm -rf /app/sp/ui/app-centre/${params.profile}/${params.module}/dist/*" echo "/app/sp/ui/sales/${params.profile}/${params.module}/*" sshPut remote: remote, from: "${params.modulePrefix}/${params.module}/dist/", into: "/app/sp/ui/app-centre/${params.profile}/${params.module}/" echo "${params.modulePrefix}/${params.module}/dist/,/app/sp/ui/app-centre/${params.profile}/${params.module}/" sshCommand remote: remote, command: "cp -rf /app/sp/ui/app-centre/${params.profile}/${params.module}/dist/* /app/sp/ui/app-centre/${params.profile}/${params.module}/" } } } } stage('Maven 编译') { when { environment name: 'modulePrefix', value: 'java' } agent { docker { image 'maven:3-amazoncorretto-11' //让docker 使用 host 宿主机的 m2仓库 使用root用户来运行 以让指定的~/.m2/config/setting.xml 阿里加速下载maven 依赖生效 args '-v /app:/app:z -v $HOME/.m2:/root/.m2:z -u root' reuseNode true } } steps { echo "编译 API 代码" sh "mvn clean package -U -am -pl ${params.module} -P${params.profile} -Dmaven.test.skip=true" } } // 项目打包到镜像并推送到镜像仓库 stage('构建Docker镜像') { when { environment name: 'modulePrefix', value: 'java' } steps { echo "构建Dcoker镜像-------------------" script { docker.withRegistry(DOCKER_LOGIN_REGISTRY, DOCKER_REGISTRY) { BASE_IMAGE = 'registry.cn-shenzhen.aliyuncs.com/storlead/openjdk:11' sh "docker pull ${BASE_IMAGE}" sh """ echo ' FROM ${BASE_IMAGE} COPY ${params.module}/target/${params.module}.jar app.jar EXPOSE ${API_PORT} EXPOSE ${API_REMOTE_DEBUG_PORT} HEALTHCHECK --interval=1m --timeout=10s CMD curl -f http://localhost:${API_PORT}/${API_NAMESPACE_RESTFUL}/actuator ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom", "-Djava.awt.headless=true","-Dspring.profiles.active=${params.profile}", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:${API_REMOTE_DEBUG_PORT}","-jar","/app.jar"]' > Dockerfile docker build -t ${DOCKER_IMG_NAME} . """ sh "docker push ${DOCKER_IMG_NAME}" } } } } stage('启动服务') { when { environment name: 'modulePrefix', value: 'java' } steps { withCredentials([ usernamePassword(credentialsId: 'storleadHW', usernameVariable: 'usernameHW', passwordVariable: 'passwordHW'), usernamePassword(credentialsId: 'storlead', usernameVariable: 'username', passwordVariable: 'password'), usernamePassword(credentialsId: 'reg-aliyun', usernameVariable: 'aliUsername', passwordVariable: 'aliPassword') ]) { script { echo "启动服务" echo "${aliPassword}" echo "docker login -u ${aliUsername} -p ${aliPassword} ${DOCKER_LOGIN_REGISTRY}" def remote = [:] remote.name = "${SERVER_HOST}" remote.host = "${SERVER_HOST}" remote.port = 53023 remote.user = username remote.password = password remote.allowAnyHosts = true //因为使用 docker swarm 发布 只能在 manage node 执行部署 if (params.profile == "prod") { remote.port = 22 remote.user = "root" remote.user = usernameHW remote.password = passwordHW } if (PUSH_DOCK_IMG) { //docker 认证 sshCommand remote: remote, command: "docker login -u ${aliUsername} -p ${aliPassword} ${DOCKER_LOGIN_REGISTRY}" //如果选择推送才使用远程的版本 如果不选择推送到远程则直接运行本机刚打包的镜像版本即可 sshCommand remote: remote, command: "docker pull ${DOCKER_IMG_NAME}" } sh """ echo ' version: "3.7" services: ${params.module}-${params.profile}: image: ${DOCKER_IMG_NAME} deploy: replicas: ${SWARM_INIT_REPLICAS_NUM} placement: constraints: - 'node.hostname == ${SERVER_HOST_NAME}' update_config: parallelism: 1 delay: 1m restart_policy: condition: on-failure # 最多连续重试3次如果仍然失败则放弃重试 max_attempts: 3 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:${API_PORT}/${API_NAMESPACE_RESTFUL}/actuator"] interval: 1m timeout: 5s retries: 3 start_period: 30s environment: - "TZ=Asia/Shanghai" - "SPRING_PROFILES_ACTIVE=${params.profile}" volumes: - /app:/app - /mnt/vdb/storlead:/mnt/vdb/storlead ports: - "${API_PORT}:${API_PORT}" - "${API_REMOTE_DEBUG_PORT}:${API_REMOTE_DEBUG_PORT}" networks: - vonedao_net extra_hosts: - "www.storlead.com:172.18.194.161" - "node1:110.41.82.21" - "node2:110.41.174.46" - "node3:121.37.226.174" - "test1.storlead.com:172.18.194.168" - "test2.storlead.com:172.18.194.163" networks: vonedao_net: external: true ' > ${params.module}-${params.profile}-stack.yml """ // if (params.profile =="dev") { // sh "docker stack deploy -c ${ARTIFACTID}-${params.profile}-stack.yml ${ARTIFACTID}-${params.profile}" // sh "docker ps -f name=${ARTIFACTID} -q | xargs --no-run-if-empty docker container stop" // sh "docker container ls -a -fname=${ARTIFACTID} -q | xargs -r docker container rm" // sh "docker run -d --restart=always -p ${API_PORT}:${API_PORT} -p ${API_REMOTE_DEBUG_PORT}:${API_REMOTE_DEBUG_PORT} -v /app:/app --name ${ARTIFACTID} ${DOCKER_IMG_NAME}" // } else { // 全部都以swarm 模式启动 sshPut remote: remote, from: "${params.module}-${params.profile}-stack.yml", into: "/docker/sp/${params.module}-${params.profile}-stack.yml" sshCommand remote: remote, command: "docker stack deploy --resolve-image=always --with-registry-auth -c /docker/sp/${params.module}-${params.profile}-stack.yml ${params.module}-${params.profile}" // } } } } } } }