[docker]-容器镜像管理规范

导语:记录一下相关规范。以防后续用到时找不到

容器镜像管理规范

命名规范

  • 仓库类型
    • snapshot :开发版本仓库
    • release :生产正式版本仓库
  • 仓库命名
    • snapshot : 业务/项目名称-snapshot demo-snapshot
    • release : 业务/项目名称-release demo-release
  • 镜像命名
    • DEV : demo-snapshot/demo-devops-service:branch_commitid
    • PRD: demo-release/demo-devops-service:version_commitid
    • (业务/项目名称)/应用名称/标签
  • 标签命名
    • 分支名_提交ID
    • 版本号_提交ID

提交ID的意义: 减少重复构建。 每次发布获取当前发布分支中的最后一次提交的id进行匹配,在harbor镜像仓库中进行搜索,如果存在则跳过构建直接发布,如果不存在则进行构建步骤再发布。

img

镜像清理策略

随着镜像越来越多,频繁更新导致Harbor镜像仓库容量很快爆满。

  • snapshot仓库:每定时清理几天前的镜像
  • release仓库:版本发布完成后,清除版本其他镜像

因为版本分支进行正式环境发布的时候,可能会出现问题。进行修复后镜像仓库中会出现 1.1.1_xxxxxx1,1.1.1_xxxxxx2的镜像标签。假如1.1.1_xxxxxx2是我们正式发布的版本,则发布完成后。清理掉1.1.1_xxxxxx1。

主要通过以下2条命令获取短位的COMMITID,生成tag

                    GIT_COMMITID= sh(  returnStdout: true, script: 'echo -n `git rev-parse --short HEAD`')
                    Tag="${BRANCH}_${GIT_COMMITID}"

jenkinsfile 如下

#!groovy

pipeline {
    agent {
        label "10.10.3.245"
    }

    //定义构建参数
    parameters {
       
        
        imageTag(name: 'DOCKER_IMAGE', description: '应用使用的基础镜像',
            image: 'base/lung', filter: '.*', defaultTag: 'ge930',
             registry: 'http://harbor.deepwise.com', credentialId: '18060a85-ebcf-4aa4-bca7-b267c07497f3', tagOrder: 'NATURAL') 
        gitParameter name: 'BRANCH', type: 'PT_BRANCH_TAG', branchFilter: '(.*\\b)', listSize: '10', defaultValue: '20220531_sp2', description: '代码的分支', selectedValue: 'TOP', sortMode: 'DESCENDING'
        choice(name: 'NameSpace', choices: ['default','dev01','dev02','dev03','dev04','dev05','test01','test02','test03','test04','test05'], description: '请选择需要发布的环境----namespace')
    }

    //定义变量
    environment {
        Unzip_Path="/data1/TestPackage/lung/cta/"
        //Tag = "`date '+%Y-%m-%d'-${BUILD_NUMBER}`"
        // 项目名称
        // PROJECT = 'DxAI'
        // 工程名称
        // APP_NAME = "dxPython"
        // 发布环境
        // DEPLOY_ENV = "${params.发布环境}"
        // 仓库地址
        // GIT_REPO = "${params.GIT_REPO}"
        // 仓库分支
        // BRANCH = "${params.BRANCH}"
        // 备份路径
        // BAK_PATH = "/mnt/backup/"
        // 模块路径
        // APP_PATH = "/data1/docker_data/wwwroot/research"
        //默认邮件接收人
        // DEFAULT_EMAIL = ''
        //负责邮件接收人
        // OWNER_EMAIL = ''
        //PL邮件接收人
        // PL_EMAIL = ' '
    }

    //来源全局设置配置的变量
//     tools {
// //        jdk 'java-8'
//         maven 'maven-3.6.0'
//     }

    options {
        timestamps()
        //保持构建的最大个数
        buildDiscarder(logRotator(numToKeepStr: '10'))
    }




    //执行任务模块
    stages {
        //拉取代码模块
        stage('Checkout weight') {
            steps {
                //deleteDir()
                echo "---------------------------------------------------------------------------------"
                echo "Starting Checkout Code......"
                echo "---------------------------------------------------------------------------------"
                script {
                    echo "starting fetchCode from http://xxx.git......"
                    checkout([$class           : 'GitSCM',
                              branches         : [[name: "${BRANCH}"]],
                              doGenerateSubmoduleConfigurations: false,
                              extensions: [[$class: 'CloneOption', noTags: false, reference: '', shallow: false, timeout: 60000],[$class:'CheckoutOption',timeout:60000]],
                              userRemoteConfigs: [[credentialsId: '81f18226-d36e-4a0e-bd0e-b936843ae77b',
                                                   url          : "http://xxx.git",]]
                    ])
                }
            }
        }
        stage('Checkout lung') {
            steps {
                //mkdir lung

                //deleteDir()
                echo "---------------------------------------------------------------------------------"
                echo "Starting Checkout Code......"
                echo "---------------------------------------------------------------------------------"
                println env.WORKSPACE
			 //   dir("/data/jenkins/workspace/lung"){
			 //       sh "sleep 300"
			 //       sh "echo pwd"
				//     sh "pwd"
			 //   }

                script {
                    wrap([$class: 'BuildUser']) {
                    def deploylog="${BUILD_USER} use pipeline  '${JOB_NAME}(${BUILD_NUMBER})' "
                    println deploylog
                    buildName "#${BUILD_NUMBER}-^${BRANCH}^-${BUILD_USER}"
                    HTTPD_LOCATION= sh(  returnStdout: true, script: 'git show -s  |grep -vE "commit|Date" |grep -v "^$"')
                  
                    buildDescription "${HTTPD_LOCATION}" 
                    GIT_COMMITID= sh(  returnStdout: true, script: 'echo -n `git rev-parse --short HEAD`')
                    Tag="${BRANCH}_${GIT_COMMITID}"
                    
                    
                  }
                    echo "starting fetchCode from http://xxx.git......"
                    checkout([$class           : 'GitSCM',
                              branches         : [[name: "${BRANCH}"]],
                              doGenerateSubmoduleConfigurations: false,
                              extensions: [[$class: 'CleanBeforeCheckout', deleteUntrackedNestedRepositories: true],[$class: 'CloneOption', noTags: false, reference: '', shallow: false, timeout: 60000],[$class:'CheckoutOption',timeout:60000],[$class: 'RelativeTargetDirectory', relativeTargetDir: '/data/jenkins/workspace/lung-base']],
                              userRemoteConfigs: [[credentialsId: '81f18226-d36e-4a0e-bd0e-b936843ae77b',
                                                  url          : "http://xxx.git",]]
                    ])
                }
            }
        }


        //打包模块
        stage('Package') {
            steps {
                echo "---------------------------------------------------------------------------------"
                echo "Starting Gradlew package ......"
                echo "---------------------------------------------------------------------------------"
                script {
                    sh """
                        echo "package"
                        rsync -avP  --exclude=.git /data/jenkins/workspace/lung-base/*  /data/package/lung/ 
                        rsync -avP  --exclude=.git ${WORKSPACE}/*  /data/package/lung/
                        rsync -avP  --exclude=.git /data/jenkins/workspace/aiclassifier  /data/package/
                       """
                }
            }
        }

        stage('build') {
            steps {
                echo "---------------------------------------------------------------------------------"
                echo "Starting Publish apk to Remote ......"
                echo "---------------------------------------------------------------------------------"
                script {
                    sh """
                        echo Tag ${Tag}
                        echo TestTag $TestTag 
                        cd /data/package/
                        echo base image name: ${DOCKER_IMAGE}
                        echo image name: harbor.deepwise.com/dev/${JOB_NAME}:${Tag}
                        echo FROM harbor.deepwise.com/${DOCKER_IMAGE} > Dockerfile
                        echo COPY lung /root/lung >> Dockerfile
                        echo COPY aiclassifier /root/aiclassifier >> Dockerfile
                        echo harbor.deepwise.com/dev/${JOB_NAME}:${Tag}
                        cat Dockerfile
                        echo "docker build -t harbor.deepwise.com/dev/${JOB_NAME}:${Tag} ."
                        docker build -t harbor.deepwise.com/dev/${JOB_NAME}:${Tag} .
                        
                        docker push harbor.deepwise.com/dev/${JOB_NAME}:${Tag}
                        
                        whoami
                       # echo ssh root@172.16.20.88 "kubectl set image deployment/aiserver-dp  aiserver=harbor.deepwise.com/dev/${JOB_NAME}:${Tag} -n ${NameSpace} "
                       # ssh root@172.16.20.88 "kubectl set image deployment/aiserver-dp  aiserver=harbor.deepwise.com/dev/${JOB_NAME}:${Tag} -n ${NameSpace} "
                    """
                }
            }
        }

        stage('Install') {
            // agent {
            //     label "172.16.40.245"
            // }
            steps {
                echo "---------------------------------------------------------------------------------"
                echo "Starting Install Application......"
                echo "---------------------------------------------------------------------------------"
                script {
                    sh """
                        echo 123
                       """
                }
            }
        }
    }
}

构建容器镜像

编写Dockerfile

FROM nginx:latest

COPY dist /usr/share/nginx/html

复制

构建镜像

docker build -t demo-web-app:1.1.1 .

复制

上传镜像

docker push demo-web-app:1.1.1

复制

一个完整的Jenkinsfile

pipeline {
    agent {node {label "master"}}
    stages {
        stage('WebBuild') {
            steps {
                script {
                    docker.image('node:10.19.0-alpine').inside('-u 0:0 -v /var/jenkins_home/.npm:/root/.npm') {


                        sh """
                            id 
                            ls /root/.npm

                            ls /root/ -a
                            npm config set unsafe-perm=true
                            npm config list
                            npm config set cache  /root/.npm
                            #npm config set registry https://registry.npm.taobao.org
                            npm config list
                            ls 
                            cd demo && npm install  --unsafe-perm=true && npm run build  && ls -l dist/ && sleep 15 
                        """
                    }
                }
            }
        }

      stage("BuildImage"){
        steps {
          script{


            sh """
                #构建镜像
                cd demo
                docker build -t demo/demo-web-app:1.1.1_xxxxxxxx1 .

                #docker push demo/demo-web-app:1.1.1_xxxxxxxx1

            """

          }
        }
      }
    }
}

复制

构建完成后,运行镜像进行测试

docker run -itd -p 8080:80 --name nginx-server demo/demo-web-app:1.1.1_xxxxxxxx1

镜像清理策略

如果我们使用的是Harbor镜像仓库,我们可以给每个项目管理员授权定时手动清理镜像,我们也可以通过Harbor的接口进行自动化清理。在此举例通过Jenkins自动化清理。

这里列举了 获取镜像标签和根据标签删除镜像的方法。(注意这个实例仅供参考,在生产请慎用。不是说不能用,而是涉及到删除镜像,如果误删影响很大。)

#!groovy
@Library('jenkinslibrary@master') _

def tools = new org.devops.tools()

String registryName = "${env.registryName}"
String serviceName = "${env.serviceName}"
String tagName = "${env.tagName}"
def harborProjects = []

currentBuild.description = "Trigger by ${serviceName} ${tagName}"


pipeline {
    agent { node { label "build"} }

    stages{

        stage("GetHarborTags"){
            steps{
                timeout(time:5, unit:"MINUTES"){
                    script{
                        tools.PrintMes("获取Harbor仓库中的项目信息","green")
                        println(serviceName)

                        try {
                            response = httpRequest authentication: 'harbor-admin,
                                                   url: "https://registry.demo.com/api/repositories/${registryName}/${serviceName}/tags",
                                                   ignoreSslErrors: true
                            //println(response.content)
                            response = readJSON text: """${response.content}"""

                        } catch(e){
                            response = ['name':'']
                            println(e)
                            println("Harbor镜像不存在此标签!")

                        }

                        /*println(tagName)
                        for (tagname in response){
                            //println(response)
                            harborProjects << tagname['name']
                        }

                        println(harborProjects)*/

                    }
                }
            }
        }



        stage("DeleteHarborTags"){
            steps{
                timeout(time:20, unit:"MINUTES"){
                    script{
                        tools.PrintMes("总共找到 ${harborProjects.size()} 个标签","green")
                        sumImageNum = harborProjects.size()
                        for (tag in harborProjects){
                            sumImageNum -= 1

                            tools.PrintMes(" ${sumImageNum}  Delete Tags ---> ${registryName} --> ${serviceName} --> ${tag} ","green")

                            httpRequest httpMode: 'DELETE',
                                       authentication: 'c016027e-0573-4246-93cf-f4a55b08a86a',
                                       url: "https://registry.demo.com/api/repositories/${registryName}/${serviceName}/tags/${tag}",
                                       ignoreSslErrors: true

                            sleep 1
                        }
                    }
                }
            }
        }
    }


    post {
        always{
            script{
                cleanWs notFailBuild: true 
            }
        }
    }
}

参考

https://cloud.tencent.com/developer/article/1599849

https://github.com/zeyangli

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爷来辣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值