k8s部署gin-vue-admin框架、gitlab-ci、jenkins pipeline 、CICD

测试环境使用的jenkins
正式环境使用的gitlab-ci

测试环境

  1. 创建yaml文件

    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: dtk-go-tiktok-admin-config
    labels:
    app.kubernetes.io/name: dtk-go-tiktok-admin
    app.kubernetes.io/business: infrastructure
    app.kubernetes.io/runtime: golang
    app.kubernetes.io/tier: backend
    app.kubernetes.io/environment: test
    app.kubernetes.io/managed-by: yong.xd
    data:
    config.yaml: |
    max-age: 0
    show-line: true
    log-in-console: true


    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: dtk-vue-tiktok-admin-config
    labels:
    app.kubernetes.io/name: dtk-go-tiktok-admin
    app.kubernetes.io/business: infrastructure
    app.kubernetes.io/runtime: golang
    app.kubernetes.io/tier: front
    app.kubernetes.io/environment: test
    app.kubernetes.io/managed-by: yong.xd
    data:
    default.conf: |
    server{

         listen       80 default_server;
         server_name  _;
         access_log   /dev/stdout;
         error_log    /dev/stdout;
         root         /opt/app/dist/;
         location / {
                 try_files $uri $uri/ /index.html;
             }
         location /api {
           proxy_set_header Host $http_host;
           proxy_set_header  X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header X-Forwarded-Proto $scheme;
           rewrite ^/api/(.*)$ /$1 break;  #重写
           add_header 'dtk-debug' 'api';
     #一个deployment2个pod是网络资源是共享的,所以可以直接代理
           proxy_pass http://127.0.0.1:8888; # 设置代理服务器的协议和地址
           }
    
        location /api/swagger/index.html {
          proxy_pass http://127.0.0.1:8888/swagger/index.html;
          }
         location /health {
           access_log off;
           return 200;
         }
     }
    

    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: dtk-go-tiktok-admin
    labels:
    app.kubernetes.io/name: dtk-go-tiktok-admin
    app.kubernetes.io/business: infrastructure
    app.kubernetes.io/runtime: golang
    app.kubernetes.io/tier: backend
    app.kubernetes.io/environment: test
    app.kubernetes.io/managed-by: yong.xd
    spec:
    replicas: 1
    selector:
    matchLabels:
    app.kubernetes.io/name: dtk-go-tiktok-admin
    app.kubernetes.io/business: infrastructure
    app.kubernetes.io/runtime: golang
    app.kubernetes.io/tier: backend
    app.kubernetes.io/environment: test
    app.kubernetes.io/managed-by: yong.xd
    template:
    metadata:
    labels:
    app.kubernetes.io/name: dtk-go-tiktok-admin
    app.kubernetes.io/business: infrastructure
    app.kubernetes.io/runtime: golang
    app.kubernetes.io/tier: backend
    app.kubernetes.io/environment: test
    app.kubernetes.io/managed-by: yong.xd
    spec:
    imagePullSecrets:
    - name: aliyun-regcred
    serviceAccountName: default
    securityContext:
    dnsPolicy: None
    dnsConfig:
    nameservers:
    - 172.31.74.196
    searches:
    - test1.svc.cluster.local
    - svc.cluster.local
    - cluster.local

       containers:
         - name: golang
           securityContext:
             runAsUser: 0
           image: "registry.buydance.com/dataoke-test/dtk-go-tiktok-admin-golang:latest"
           volumeMounts:
           - name: config
             mountPath: /opt/app/conf/
           ports:
             - name: http
               containerPort: 8888
               protocol: TCP
           livenessProbe:
             httpGet:
               path: /health
               port: 8888
             initialDelaySeconds: 5
             periodSeconds: 20
             timeoutSeconds: 3
           readinessProbe:
             httpGet:
               path: /health
               port: 8888
             initialDelaySeconds: 5
             periodSeconds: 10
             timeoutSeconds: 3
           resources:
             requests:
               cpu: 1m
               memory: 20Mi
    
         - name: nginx
           securityContext:
           image: "registry.buydance.com/dataoke-test/dtk-go-tiktok-admin-nginx:latest"
           volumeMounts:
           - name: ng-config
             mountPath: /etc/nginx/conf.d/
           ports:
             - name: http
               containerPort: 80
               protocol: TCP
           livenessProbe:
             httpGet:
               path: /health
               port: 80
             periodSeconds: 5
           readinessProbe:
             httpGet:
               path: /health
               port: 80
             periodSeconds: 5
           resources:
             requests:
               cpu: 1m
               memory: 64Mi
             limits:
               cpu: 200m
               memory: 256Mi
       volumes:
       - name: ng-config
         configMap:
           name: dtk-vue-tiktok-admin-config
       - name: config
         configMap:
           name: dtk-go-tiktok-admin-config
    

    apiVersion: v1
    kind: Service
    metadata:
    name: dtk-go-tiktok-admin
    spec:
    ports:
    - port: 80
    targetPort: 80
    protocol: TCP
    name: nginx
    - port: 8888
    targetPort: 8888
    protocol: TCP
    name: golang
    selector:
    app.kubernetes.io/name: dtk-go-tiktok-admin
    app.kubernetes.io/business: infrastructure
    app.kubernetes.io/runtime: golang
    app.kubernetes.io/tier: backend
    app.kubernetes.io/environment: test
    app.kubernetes.io/managed-by: yong.xd

  2. 启动服务

    kubectl apply -f ./ -n test1

  3. 配置jenkins

    #!/usr/bin/env groovy
    import groovy.json.JsonOutput

    String gitRepositryURL = 'https://test.com/dtk-go-tiktok-admin.git'
    String dockerRegistry = 'test.com'
    String dockerRegistryURL = 'https://test.com'
    String dockerRegistryNameSpace = 'dataoke-test'
    #dockerfile路径
    String kubeManifestsRepo = '/home/jenkins/repo/dtk-kubernetes-test/app'
    Map dockerFiles = ["nginx":"Dockerfile.test.nginx", "golang":"Dockerfile.test.golang"]
    Map dockerImages = [:]
    boolean notify = false

    String jobBaseName = env.JOB_NAME[4..-1]
    String jobK8sName = jobBaseName.replaceAll('_', "-")

    Map commitInfo = [:]
    Map buildInfo = [:]

    commitInfo.projectName = gitRepositryURL.replaceFirst(/^.*/([^/]+?).git$/, '$1')
    commitInfo.gitRepositryURL = gitRepositryURL
    buildInfo.buildId = currentBuild.id

    @NonCPS
    def newSh(String cmd) {
    def script = '#!/bin/sh +x\n' << cmd
    result = sh(returnStdout: true, script: script.toString())
    return result
    }

    pipeline {
    agent any

     options {
     	buildDiscarder logRotator(
     		artifactDaysToKeepStr: '', 
     		artifactNumToKeepStr: '', 
     		daysToKeepStr: '10', 
     		numToKeepStr: '10'
     		)
     }
    
     parameters {
         
         choice( 
         	name: 'PENV',
         	choices: [
         		'dev1',
         		'dev2',
         		'test1',
         		'test2', 
         		'test3', 
         		'test4',
         		'test5',
                         'test6',
                         'test7',
         		'huise',
    

    'huise4',
    'huise3'
    ],
    description: '选择发布环境,默认发布至dev1测试环境'
    )

         gitParameter(
         	name: 'GIT_BRANCH', 
             type: 'PT_BRANCH_TAG',
             branchFilter: 'origin/(.*)',
             defaultValue: 'master',
             selectedValue: 'DEFAULT',
             sortMode: 'DESCENDING_SMART',
             quickFilterEnabled: true, 
             description: 'Select your branch or tag.'
         	)
     	 booleanParam(name: 'force', defaultValue: false, description: '代码重复强制发版')
     }
    
     stages {
    
     	stage('预处理') {
     		steps {
     			script {
     				def now = new Date()
     				buildInfo.buildDate = now.format("yy-MM-dd HH:mm", TimeZone.getTimeZone('UTC'))
    
     				def causes = currentBuild.getBuildCauses()
     				buildInfo.buildUser = causes[0]['userName']
     				userList = readYaml(file:'/etc/jenkins/users.yaml')
     				if (!(PENV in userList.env.dev ) && !(buildInfo.buildUser in userList.user.allow)) {
     					error(message: "开发只能发布环境到${userList.env.dev.join(',')}")			
     				}
     				buildInfo.gitBranch = GIT_BRANCH
     				buildInfo.publishEnv = PENV
     				currentBuild.description = "k8s环境: ${PENV} 构建人:${buildInfo.buildUser} 分支: ${GIT_BRANCH}"
     				newSh("check.py -u ${buildInfo.buildUser} -e ${PENV}")
     			}
     		}
     	}
    
     	stage('同步代码仓库') {
     		steps {
     			script {
     				def scmVars = checkout([
     							$class: 'GitSCM', 
     							branches: [[name: "${GIT_BRANCH}"]], 
     							extensions: [[$class: 'CheckoutOption', timeout: 20], [$class: 'CloneOption', depth: 1]], 
     							userRemoteConfigs: [[credentialsId: "5411496d-3606-4855-ab9c-2e4453cd2880", url: "${gitRepositryURL}"]]
     							])
     				commitInfo.gitCommit = scmVars.GIT_COMMIT
     				commitInfo.gitBranch = GIT_BRANCH
     				commitInfo.xiangmu_name = env.JOB_BASE_NAME
     				commitInfo.commitDate = newSh('git log --pretty=format:"%ci" -1')
     				commitInfo.cmmitMessage = newSh('git log --pretty=format:"%s" -1')
    
     				String gitDiff = newSh('git diff HEAD^ HEAD')
     				def committer = [:]
     				committer.name = newSh('git log --pretty=format:"%cn" -1')
     				committer.email =  newSh('git log --pretty=format:"%ce" -1')
     				commitInfo.committer = committer
     				
     				String consoleStdout = "\n\n---------SYNCHRONIZE GIT REPOSITORY---------\nGit repo sync successfully.\n\n" + JsonOutput.prettyPrint(JsonOutput.toJson(commitInfo))
     				println(consoleStdout)
    
     				consoleStdout = "\n\n---------CHANGE LOGS---------\nGit diff:\n\n" + gitDiff
     				println(consoleStdout)
     				getDatabaseConnection(type: 'GLOBAL') {
     					def sqlString="select commit_seccec from jenkins_commit.jenkins_jilu where xm_name = ? and env = ?"
                         def params=[commitInfo.xiangmu_name,PENV]
                         def rest_null = sql sql:sqlString,parameters:params
     					if (rest_null.size() == 0){
     					  def sqlString2="insert  into  jenkins_commit.jenkins_jilu(xm_name,env,commit_seccec)   values(?,?,?)"
                           def params2=[commitInfo.xiangmu_name,PENV,commitInfo.gitCommit]
     					  sql sql:sqlString2,parameters:params2
     					  println("mysql插入数据")
     					}
     					if (rest_null.size() >= 1) {
     						   def Map rest = rest_null.get(0)
                         if (rest.get("commit_seccec") == commitInfo.gitCommit && force == "false"){
                         currentBuild.description = "k8s环境: ${PENV} 构建人:${buildInfo.buildUser} 分支: ${GIT_BRANCH} 构建失败: 代码重复不发版"
     						   println("代码没有变化不做发版")
                                error "上一个版本和现在正在发的版本一致,不做发版"
     						   }
     					}
     			
     				}
     			}
     		}
     	}
    
     	stage('构建') {		
     		agent {
           		docker { 
               		image 'registry.buydance.com/dataoke-test/golang:1.19'
               		args '--user root -v /data/jenkins_build_cache/.cache:/.cache'
               		args '--user root -v /data/lib/go:/go'
               		reuseNode true
           		}	
       		}
    
         	steps {
             	script {
     				env.STAGE = "goujian"
             		def now = new Date()
     				String buildDate = now.format("yy-MM-dd HH:mm", TimeZone.getTimeZone('UTC'))
    
          			sh (script: '#!/bin/sh +x\n' + '''
          			cd ./server
          			mkdir -p .cache
              		export GO111MODULE=on
              		export GOPROXY=https://goproxy.cn,direct
              		export GOPRIVATE="gitlab.buydance.com/*"
              		export CGO_ENABLED=0
              		go mod  tidy
              		go build -o main
          			'''
          			)
    
            			def files = findFiles(glob: '**/main')
            			String artifactPath = files[0].path
            			String sha1Checksum = sha1(file: artifactPath)
            			String sha256Checksum = sha256(file: artifactPath)
             				
    
    
             		consoleStdout = "\n\n---------BUILD RESULTS---------\nBuild info generated successfully.\n\n" + JsonOutput.prettyPrint(JsonOutput.toJson(buildInfo))
             		println(consoleStdout)
         		}	
     		}
     	}
     	
     	stage('构建vue') {		
     		agent {
           		docker { 
               		image 'node:14.19.3-alpine3.15'
                     args '--user root -v /data/jenkins_build_cache/.cache:${HOME}/.cache'
                     args '--user root -v /data/lib/composer:/root/.composer'
                     reuseNode true
           		}	
       		}
    
         	steps {
             	script {
             		sh """
     				cd ./web
                     npm config set puppeteer_download_host=https://npm.taobao.org/mirrors
                     npm i --registry=https://registry.npm.taobao.org
                     npm run build
                     """
     				
             		consoleStdout = "\n\n---------BUILD RESULTS---------\nBuild info generated successfully.\n\n" + JsonOutput.prettyPrint(JsonOutput.toJson(buildInfo))
             		println(consoleStdout)
         		}	
     		}
     	}
     	
    
     	stage('Docker') {
     		steps {
     			script {
     				env.STAGE = "DOCKERFIEL"
     			//	docker.withRegistry(dockerRegistryURL, '8f1a40fa-3258-4717-825c-a9f87299916d') {
     				docker.withRegistry(dockerRegistryURL) {
     					
     					String dockerFile = kubeManifestsRepo + '/' + jobBaseName + '/' + 'Dockerfile.test.nginx'
     					    
     					if (!fileExists(dockerFile)) {
     						dockerFile = kubeManifestsRepo + '/' + jobK8sName + '/' + 'Dockerfile.test.nginx'
     					}
    
     					String dockerRepository = dockerRegistry + '/' + dockerRegistryNameSpace + '/' + jobK8sName + '-' + 'nginx'
     					def customImage = docker.build(dockerRepository, "-f ${dockerFile} .")
     					customImage.push(commitInfo.gitCommit)
     					customImage.push('latest')
     					
     					dockerImages.nginx = dockerRepository + ':' + commitInfo.gitCommit
    
     					dockerFile = kubeManifestsRepo + '/' + jobBaseName + '/' + 'Dockerfile.test.golang'
     					    
     					if (!fileExists(dockerFile)) {
     						dockerFile = kubeManifestsRepo + '/' + jobK8sName + '/' + 'Dockerfile.test.golang'
     					}
    
     					dockerRepository = dockerRegistry + '/' + dockerRegistryNameSpace + '/' + jobK8sName + '-' + 'golang'
     					customImage = docker.build(dockerRepository, "-f ${dockerFile} .")
     					customImage.push(commitInfo.gitCommit)
     					customImage.push('latest')
    
     					dockerImages."golang" = dockerRepository + ':' + commitInfo.gitCommit
     				}
     			}
     		}
     	}
    
     	stage('部署') {
     		steps {
     			script {
     				env.STAGE = "bushu"
     				dockerImages.each { k, v -> 
     					newSh("kubectl -n ${PENV} set image deployment/${jobK8sName} ${k}=${v}")
     					newSh("kubectl -n ${PENV} rollout status deployment/${jobK8sName} --timeout=2m")
     				}
     				String content = "![screenshot](https://comquent.de/wp-content/uploads/CQ-Pipeline-Kurs.png)\n\n### Jenkins Pipeline\n>**构建信息**:\n>- 构建项目: ${jobBaseName}\n>- 构建id: ${currentBuild.number}\n>- 构建人: ${buildInfo.buildUser}\n>- 构建分支: ${GIT_BRANCH}\n>- 发布环境: ${PENV}\n>**版本信息**:\n>- commit_hash: ${commitInfo.gitCommit}\n>- commit_date: ${commitInfo.commitDate}\n>- commit_message: ${commitInfo.cmmitMessage}\n>- committer: ${commitInfo.committer.name}"	
     				def workflowMessage = [
     					"msgtype": "actionCard",
     					"actionCard":[
     						"title":"构建信息",
     						"text":content,
     						"btnOrientation": "0",
     						"btns": [
     							[
     								"title": "详细信息",
     								"actionURL": "https://k8sjenkins.haojiequ.com/blue/organizations/jenkins/k8s_dtk_go_app_api/detail/k8s_dtk_go_app_api/${currentBuild.number}/pipeline"
     							],
     							[
     								"title": "日志监控",
     								"actionURL": "http://k8skibana.haou.com/app/kibana#/discover?_g=()&_a=(columns:!(_source),index:'18d51920-96c3-11eb-811f-1383c86a1d0',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))"
     							],
     						]
     					]
     				]	
    
     				String workflowMessageJSON = JsonOutput.toJson(workflowMessage)
     				timeout(unit: 'SECONDS', time: 30) {
     					newSh("curl 'https://oapi.dingtalk.com/robot/send?access_token=9e91f6860736ff69e7f6f986179e154e497b70e26fd749c' -s -H 'Content-Type: application/json' -d '${workflowMessageJSON}'")
     				}
     			}
     		}
     	}
     	stage("commit入库"){
              steps {
                   script{
                         getDatabaseConnection(type: 'GLOBAL') {
     			        def sqlString3="update jenkins_commit.jenkins_jilu set commit_seccec=?    where xm_name=? and env=?;"
                         def params3=[commitInfo.gitCommit,commitInfo.xiangmu_name,PENV]
                         sql sql:sqlString3,parameters:params3
     			  }
     			  }
     		 }
     	}
     }
     post {
     	failure {
     		script{
     		if (STAGE == "goujian") {
     			println("----> goujian失败")
     		}
     	    if (STAGE == "bushu") {
     		   println("----> bushu失败")		   
     		}
     		if (STAGE == "DOCKERFIEL") {
     			println("----> DOCKERFIEL失败")
     		}
     
     		}
     	}
     }
    

    }

  4. 配置nginx

    upstream dtk-vue-tiktok-admin {
    server dtk-go-tiktok-admin weight=1 max_fails=0 fail_timeout=0s;
    keepalive 20;
    }

    server {
    listen 80;
    listen 443 ssl;
    server_name test.com;
    access_log /var/log/nginx/dtest.com.access.log json;
    error_log /var/log/nginx/dtest.com.error.log;
    ssl_certificate conf.d/dtkcert/test.com.pem;
    ssl_certificate_key conf.d/dtkcert/test.com.key;
    more_set_headers 'Access-Control-Allow-Headers: Cookie,DNT,X-CSRF-Token,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,Auth-token';
    more_set_headers 'Access-Control-Allow-Origin: *';
    more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT';
    more_set_headers 'Access-Control-Allow-Credentials: true';
    default_type 'text/html';
    set $backend 'dtk-vue-tiktok-admin';

    include public/deny.conf;
    location / {
    proxy_pass http://$backend;
    }

    location ~ /.ht {
    deny all;
    }
    }

  5. jenkins机器上的dockerfile

    [root@k8s-jenkins dtk-go-tiktok-admin]# cat Dockerfile.test.golang
    FROM test.com/dataoke-test/alpine:3.12-CST as test
    WORKDIR /opt/app
    COPY $CI_PROJECT_DIR/server/main /opt/app/main
    CMD ["/opt/app/main", "-c", "/opt/app/conf/config.yaml"]

    [root@k8s-jenkins dtk-go-tiktok-admin]# cat Dockerfile.test.nginx
    FROM test.com/dataoke-test/openresty:base
    WORKDIR /opt/app/dist/
    COPY --chown=nobody:nobody web/dist /opt/app/dist


线上环境配置

  1. yaml其它都一样除了svc,因为svc需要绑定slb地址

    apiVersion: v1
    kind: Service
    metadata:
    name: dtk-go-tiktok-admin
    annotations:
    #开启slb使用
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-force-override-listeners: "true"
    #slb地址
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: lb-2ze1hpcomc
    # service.beta.kubernetes.io/alibaba-cloud-loadbalancer-protocol-port: "http:9090"
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-scheduler: "wrr"
    namespace: default
    spec:
    type: LoadBalancer
    externalTrafficPolicy: Local
    ports:
    - port: 16107 #slb端口
    targetPort: 80 #pod服务端口
    protocol: TCP
    selector:
    app.kubernetes.io/name: dtk-go-tiktok-admin
    app.kubernetes.io/business: infrastructure
    app.kubernetes.io/runtime: golang
    app.kubernetes.io/tier: backend
    app.kubernetes.io/environment: prod
    app.kubernetes.io/managed-by: yong.xd

  2. 启动

    cat .gitlab-ci.yml

    stages:

    • build
    • package
    • docker
    • deploy
    • notify

    build:
    stage: build
    image: test.com/dataoke-prod/golang:1.19-with-repo-cert
    cache:
    key:
    files:
    - go.mod
    paths:
    - .cache/pkg
    artifacts:
    expire_in: 20 mins
    untracked: false
    paths:
    - $CI_PROJECT_DIR/server/main
    script:

    package:
    stage: package
    image: test.com/dataoke-prod/node:14.19.3-alpine3.15
    script:

    docker:
    stage: docker
    image: test.com/dataoke-prod/kaniko-executor:debug
    script:

    • mkdir -p /kaniko/.docker
    • echo "${DOCKER_AUTH_CONFIG}" > /kaniko/.docker/config.json
    • /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile.prod.nginx --destination test.aliyuncs.com/dataoke-prod/echo ${CI_PROJECT_NAME} |sed 's@_@-@g'-nginx:${CI_COMMIT_SHORT_SHA} --destination test.aliyuncs.com/dataoke-prod/echo ${CI_PROJECT_NAME} |sed 's@_@-@g'-nginx:latest
    • /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile.prod.golang --destination test.aliyuncs.com/dataoke-prod/echo ${CI_PROJECT_NAME} |sed 's@_@-@g'-golang:${CI_COMMIT_SHORT_SHA} --destination test.aliyuncs.com/dataoke-prod/echo ${CI_PROJECT_NAME} |sed 's@_@-@g'-golang:latest
      only:
      • tags

    deploy:
    stage: deploy
    image: test.com/dataoke-prod/kubectl:1.18.1
    variables:
    GIT_STRATEGY: none
    K8S_NAME_SPACE: default
    script:

    • mkdir -p $HOME/.kube
    • echo "KUBERNETES_SECRET" >> "HOME/.kube/config"
    • kubectl version
    • kubectl get deployments.apps -n ${K8S_NAME_SPACE}
    • kubectl -n ${K8S_NAME_SPACE} set image deployment/echo ${CI_PROJECT_NAME} |sed 's@_@-@g' nginx=test.aliyuncs.com/dataoke-prod/echo ${CI_PROJECT_NAME} |sed 's@_@-@g'-nginx:${CI_COMMIT_SHORT_SHA} golang=test.aliyuncs.com/dataoke-prod/echo ${CI_PROJECT_NAME} |sed 's@_@-@g'-golang:${CI_COMMIT_SHORT_SHA} --record
    • kubectl rollout status deployment/echo ${CI_PROJECT_NAME} |sed 's@_@-@g'
      only:
      • tags

    notifyFailWeChat:
    stage: notify
    image: test.aliyuncs.com/dataoke-prod/curl-image:v1
    script:
    - curl 'https://oapi.dingtalk.com/robot/send?access_token=6147ec1eb7d8b9bd5cd1b15f1c' -H 'Content-Type:application/json' -d "{"msgtype":"text","text":{"content":"CI_PROJECT_NAME项目构建失败\n>本次构建由:GITLAB_USER_NAME 触发\n>项目名称:CI_PROJECT_NAME\n>提交号:CI_COMMIT_SHA\n>提交日志:CI_COMMIT_MESSAGE\n>构建分支:CI_COMMIT_BRANCH\n>流水线地址:[CI_PIPELINE_URL](CI_PIPELINE_URL)"}}"

    only:
    - tags
    when: on_failure

    构建成功时的通知消息

    notifySuccessWeChat:
    stage: notify
    image: test.aliyuncs.com/dataoke-prod/curl-image:v1
    script:
    - curl 'https://oapi.dingtalk.com/robot/send?access_token=d6147ec1eb7d8b9bd5cd1b15f1c' -H 'Content-Type:application/json' -d "{"msgtype":"text","text":{"content":"CI_PROJECT_NAME项目构建成功\n>本次构建由:GITLAB_USER_NAME 触发\n>项目名称:CI_PROJECT_NAME\n>提交号:CI_COMMIT_SHA\n>提交日志:CI_COMMIT_MESSAGE\n>构建分支:CI_COMMIT_BRANCH\n>流水线地址:[CI_PIPELINE_URL](CI_PIPELINE_URL)"}}"
    only:
    - tags
    when: on_success

  3. 配置dockerfile

    cat Dockerfile.prod.golang

    FROM test.aliyuncs.com/dataoke-prod/alpine:3.12-CST as prod
    WORKDIR /opt/app
    COPY $CI_PROJECT_DIR/server/main /opt/app/main
    CMD ["/opt/app/main", "-c", "/opt/app/conf/config.yaml"]

    cat Dockerfile.prod.nginx

    FROM test.aliyuncs.com/dataoke-prod/openresty:base
    WORKDIR /opt/app/dist/
    COPY --chown=nobody:nobody web/dist /opt/app/dist

  4. 配置nginx

    upstream dtk-go-tiktok-admin {
    #svc内网ip
    server 192.168.10.123:16107 weight=1 max_fails=0 fail_timeout=0s;
    keepalive 20;
    }

    server {
    listen 80;
    listen 443 ssl;
    server_name test.com;
    access_log /var/log/nginx/dtest.com.access.log json;
    error_log /var/log/nginx/dtest.com.error.log;
    ssl_certificate conf.d/dtkcert/test.com.pem;
    ssl_certificate_key conf.d/dtkcert/test.com.key;

    more_set_headers 'Access-Control-Allow-Headers: Cookie,DNT,X-CSRF-Token,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,Auth-token';
    more_set_headers 'Access-Control-Allow-Origin: *';
    more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT';
    more_set_headers 'Access-Control-Allow-Credentials: true';
    default_type 'text/html';
    set $backend 'dtk-vue-tiktok-admin';

    include public/deny.conf;
    location / {
    proxy_pass http://$backend;
    }

    location ~ /.ht {
    deny all;
    }
    }

  5. 结果图




原文

相关推荐
编程百晓君2 小时前
一文解释清楚OpenHarmony面向全场景的分布式操作系统
vue.js
暴富的Tdy2 小时前
【CryptoJS库AES加密】
前端·javascript·vue.js
neeef_se2 小时前
Vue中使用a标签下载静态资源文件(比如excel、pdf等),纯前端操作
前端·vue.js·excel
z千鑫2 小时前
【前端】入门指南:Vue中使用Node.js进行数据库CRUD操作的详细步骤
前端·vue.js·node.js
生产队队长4 小时前
项目练习:element-ui的valid表单验证功能用法
前端·vue.js·ui
web137656076434 小时前
WebStorm 创建一个Vue项目
ide·vue.js·webstorm
秃头女孩y4 小时前
【React中最优雅的异步请求】
javascript·vue.js·react.js
小马哥编程7 小时前
原型链(Prototype Chain)入门
css·vue.js·chrome·node.js·原型模式·chrome devtools
娃哈哈哈哈呀11 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
aherhuo13 小时前
kubevirt网络
linux·云原生·容器·kubernetes