properties([ parameters([ [$class: 'ChoiceParameter', choiceType: 'PT_SINGLE_SELECT', description: '选择要部署 API', 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"]' ] ] ], [$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: 'return["storlead-ai-api"]' ] ] ] ]) ]) pipeline { options { timestamps() } environment { GROUPID = readMavenPom().getGroupId()//com.storlead ARTIFACTID = readMavenPom().getArtifactId()//sp-project VERSION = readMavenPom().getVersion()//1.0 } // 参数 parameters { choice( name: 'profile', choices: ['prod'], 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}/${ARTIFACTID}-${params.module}-${params.profile}:${VERSION}" //镜像名 storlead/sp-project-management-prod:1.0 IMG_NAME = "${BUILD_PREFIX}/${ARTIFACTID}-${params.module}-${params.profile}:${VERSION}" PUSH_DOCK_IMG = true SERVER_HOST_NAME = "test1" echo "为指定 module 设定对应 服务器及端口" echo "处理 ${params.module} 项目" if (params.modulePrefix == "java") { echo "---- gpt" script { if (params.profile == "test") { SWARM_INIT_REPLICAS_NUM = 1 SERVER_HOST = "test1.storlead.com" API_PORT = 8780 API_REMOTE_DEBUG_PORT = 8781 SERVER_HOST_NAME = "test1" } else if (params.profile == "prod") { SWARM_INIT_REPLICAS_NUM = 1 SERVER_HOST = "110.41.82.21" API_PORT = 8780 API_REMOTE_DEBUG_PORT = 8781 SERVER_HOST_NAME = "node1" } } } echo "处理MODULE_NAMESPACE_RESTFUL" //把 module 名 从 sp-xxx 变成 xxx 也就是 项目 的 namespace if (API_NAMESPACE_RESTFUL == "storlead-ai-api") { API_NAMESPACE_RESTFUL = "/router/rest" } echo "处理镜像推送" } } } } stage('Maven 编译') { when { environment name: 'modulePrefix', value: 'java' } agent { docker { image 'maven:3-amazoncorretto-17' // 会自己下载 //让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 = 'eclipse-temurin:17' //获取最新的镜像底包 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 "启动服务" 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 == "dev") { remote.port = 22 remote.user = "root" } 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: ${ARTIFACTID}-${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}/router/rest/actuator"] interval: 1m timeout: 5s retries: 3 start_period: 30s environment: - "TZ=Asia/Shanghai" - "SPRING_PROFILES_ACTIVE=${params.profile}" volumes: - /app:/app ports: - "${API_PORT}:${API_PORT}" - "${API_REMOTE_DEBUG_PORT}:${API_REMOTE_DEBUG_PORT}" networks: - vonedao_net extra_hosts: - "test1.storlead.com:172.18.194.168" - "node1:110.41.82.21" - "node2:110.41.174.46" - "node3:121.37.226.174" networks: vonedao_net: external: true ' > ${ARTIFACTID}-${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: "${ARTIFACTID}-${params.module}-${params.profile}-stack.yml", into: "/docker/sp/${ARTIFACTID}-${params.module}-${params.profile}-stack.yml" sshCommand remote: remote, command: "docker stack deploy --resolve-image=always --with-registry-auth -c /docker/sp/${ARTIFACTID}-${params.module}-${params.profile}-stack.yml ${params.module}-${params.profile}" // } } } } } } }