Jenkinsfile 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. pipeline {
  2. agent any
  3. options {
  4. buildDiscarder(logRotator(numToKeepStr: '5'))
  5. timestamps()
  6. }
  7. parameters {
  8. string(name: 'BRANCH', defaultValue: 'uat', description: '要部署到UAT的分支')
  9. booleanParam(name: 'SKIP_APPROVAL', defaultValue: false, description: '跳过人工审批(谨慎使用)')
  10. }
  11. environment {
  12. // Dockerfile 路径(相对于代码根目录,即 Jenkins workspace)
  13. DOCKERFILE_STORE = "alien_store/Dockerfile"
  14. DOCKERFILE_GATEWAY = "alien_gateway/Dockerfile"
  15. DOCKERFILE_CONTRACT = "alien_contract/Dockerfile"
  16. // 如需推送远端 Registry,填写地址,否则留空
  17. REGISTRY = ""
  18. REGISTRY_CRED = "registry-cred-id"
  19. // 镜像标签统一使用 uat
  20. IMAGE_STORE = "${REGISTRY ? REGISTRY + '/alien_store:uat-' + env.BUILD_NUMBER : 'alien_store:uat'}"
  21. IMAGE_GATEWAY = "${REGISTRY ? REGISTRY + '/alien_gateway:uat-' + env.BUILD_NUMBER : 'alien_gateway:uat'}"
  22. IMAGE_CONTRACT = "${REGISTRY ? REGISTRY + '/alien_contract:uat-' + env.BUILD_NUMBER : 'alien_contract:uat'}"
  23. // 容器名(store 不要再用 esign-uat,会和真正的 e签宝容器撞名)
  24. CONTAINER_NAME_STORE = "alien_store_py-uat"
  25. CONTAINER_NAME_GATEWAY = "alien_gateway_py-uat"
  26. CONTAINER_NAME_CONTRACT = "alien_contract_py-uat"
  27. // 容器内端口(必须与各服务 Dockerfile 中 uvicorn 监听端口一致)
  28. PORT_STORE = "8001"
  29. PORT_GATEWAY = "43333"
  30. PORT_CONTRACT = "8002"
  31. // 使用独立的 UAT 网络
  32. DOCKER_NET = "alien_net_uat"
  33. // UAT 日志目录
  34. LOG_ROOT = "/docker/python-uat/logs"
  35. }
  36. stages {
  37. // 注意:使用 "Pipeline script from SCM" 模式时,
  38. // Jenkins 会自动 checkout 代码到 workspace,不需要在 Jenkinsfile 里再写 Checkout stage。
  39. stage('人工审批') {
  40. when {
  41. expression { !params.SKIP_APPROVAL }
  42. }
  43. steps {
  44. script {
  45. def userInput = input(
  46. id: 'UATDeployConfirm',
  47. message: "是否将分支 ${params.BRANCH} 部署到 UAT 环境?",
  48. ok: '确认部署',
  49. submitter: 'admin,release-manager',
  50. parameters: [
  51. booleanParam(name: 'CONFIRM', defaultValue: true, description: '我确认部署到UAT')
  52. ]
  53. )
  54. }
  55. }
  56. }
  57. stage('Build Images') {
  58. steps {
  59. script {
  60. // 直接在当前 workspace(Jenkins 已 checkout 的代码根)里构建
  61. if (env.REGISTRY?.trim()) {
  62. withDockerRegistry(credentialsId: env.REGISTRY_CRED, url: "") {
  63. sh "docker build -f ${DOCKERFILE_STORE} -t ${IMAGE_STORE} ."
  64. sh "docker build -f ${DOCKERFILE_GATEWAY} -t ${IMAGE_GATEWAY} ."
  65. sh "docker build -f ${DOCKERFILE_CONTRACT} -t ${IMAGE_CONTRACT} ."
  66. }
  67. } else {
  68. sh "docker build -f ${DOCKERFILE_STORE} -t ${IMAGE_STORE} ."
  69. sh "docker build -f ${DOCKERFILE_GATEWAY} -t ${IMAGE_GATEWAY} ."
  70. sh "docker build -f ${DOCKERFILE_CONTRACT} -t ${IMAGE_CONTRACT} ."
  71. }
  72. }
  73. }
  74. }
  75. stage('Push Images') {
  76. when { expression { return env.REGISTRY?.trim() as boolean } }
  77. steps {
  78. withDockerRegistry(credentialsId: env.REGISTRY_CRED, url: "") {
  79. sh "docker push ${IMAGE_STORE}"
  80. sh "docker push ${IMAGE_GATEWAY}"
  81. sh "docker push ${IMAGE_CONTRACT}"
  82. }
  83. }
  84. }
  85. stage('Deploy') {
  86. steps {
  87. script {
  88. echo ">>> UAT 部署镜像: ${IMAGE_STORE} / ${IMAGE_GATEWAY} / ${IMAGE_CONTRACT}"
  89. sh """
  90. # 创建 UAT 专用网络
  91. docker network create ${DOCKER_NET} 2>/dev/null || true
  92. # 创建日志目录
  93. mkdir -p ${LOG_ROOT}/store ${LOG_ROOT}/gateway ${LOG_ROOT}/contract
  94. # 停止旧容器(不会误删 java 的 gateway-uat / store-uat / 真正的 esign-uat 等)
  95. docker rm -f ${CONTAINER_NAME_STORE} ${CONTAINER_NAME_GATEWAY} ${CONTAINER_NAME_CONTRACT} 2>/dev/null || true
  96. # 1) 先启动下游:store
  97. # 只走 docker 内部网络,不向宿主机暴露端口(避免与 java gateway-uat 抢 8001)
  98. docker run -d --name ${CONTAINER_NAME_STORE} \\
  99. --network ${DOCKER_NET} \\
  100. -v ${LOG_ROOT}/store:/app/common/logs/alien_store \\
  101. --restart unless-stopped \\
  102. ${IMAGE_STORE}
  103. # 2) 再启动下游:contract
  104. # 只走 docker 内部网络,不向宿主机暴露端口
  105. docker run -d --name ${CONTAINER_NAME_CONTRACT} \\
  106. --network ${DOCKER_NET} \\
  107. -v ${LOG_ROOT}/contract:/app/common/logs/alien_contract \\
  108. --restart unless-stopped \\
  109. ${IMAGE_CONTRACT}
  110. # 3) 最后启动网关:gateway(依赖上面两个下游;唯一对外暴露的入口)
  111. docker run -d --name ${CONTAINER_NAME_GATEWAY} \\
  112. --network ${DOCKER_NET} \\
  113. -p ${PORT_GATEWAY}:${PORT_GATEWAY} \\
  114. -v ${LOG_ROOT}/gateway:/app/common/logs/alien_gateway \\
  115. -e STORE_BASE_URL=http://${CONTAINER_NAME_STORE}:${PORT_STORE} \\
  116. -e CONTRACT_BASE_URL=http://${CONTAINER_NAME_CONTRACT}:${PORT_CONTRACT} \\
  117. --restart unless-stopped \\
  118. ${IMAGE_GATEWAY}
  119. """
  120. }
  121. }
  122. }
  123. }
  124. post {
  125. success {
  126. echo "UAT 环境部署成功!"
  127. }
  128. failure {
  129. echo "UAT 环境部署失败,请检查日志。"
  130. }
  131. always {
  132. cleanWs()
  133. }
  134. }
  135. }