Jenkins+Docker:从 docker.inside() 提交更改

问题描述 投票:0回答:1

我有一个docker镜像需要传播到更高的环境。因此,我需要从当前图像创建另一个图像,唯一的区别是配置文件。我想知道是否有一种简单的方法可以使用 Jenkins docker pipeline 来做到这一点。

stage('Build Image') {

    steps {
       script{                                 
            docker.image('${env.IMG_NM}:${env.IMG_TAG}').inside {
                sh 'cp ${WORKSPACE}/config.txt /path_to_my_config/config.txt'
            }                                    
        }
    }            
}

在此步骤中,我将 dgo 拉入现有的 docker 映像并复制文件。我不确定如何从这里继续。如何将此 docker 容器提交为不同的映像。任何帮助表示感谢

docker jenkins jenkins-pipeline
1个回答
0
投票

我也有类似的问题。唉,

docker build
不是一个可行的解决方案,因为在我的例子中,它需要复制几十 GB 来创建构建上下文;使用映射到主机上目录的卷启动容器、运行命令,然后提交到映像要快得多。

Image.inside {...}
的主要问题是它会在内部块的末尾停止容器,因此没有容器ID可传递给
docker commit

一个可能的解决方法是使用

Image.run()
代替。它返回一个
Container
实例,其中
id
属性保存容器 ID。这样您就可以运行
docker commit
并获取提交的图像的 ID。像这样的东西:

def initialImage = docker.image("${env.IMG_NM}:${env.IMG_TAG}")
def command = "cp ${WORKSPACE}/config.txt /path_to_my_config/config.txt"
def container = image.run([:], "bash -c '${command}'")
def finalImageId = sh(
    script: "docker commit ${container.id}",
    returnStdout: true)
).trim()

container.stop()

// here, use finalImageId to add a tag, push to a repository etc.

一些陷阱:

  • inside
    块不同,您无法按顺序启动多个 shell 命令。但是您可以通过使用
    &&
    连接多个命令来构建单行命令。
  • 命令输出不会转发到控制台。要查看其输出,请使用
    sh "docker logs -f ${container.id}"
    。请注意,一旦进程退出,
    docker logs -f
    就会退出。
  • Image.run()
    几乎立即返回,让命令在后台运行。为了确保您的脚本仅在命令完成后继续,请在提交之前添加类似
    sh "exit \$(docker wait ${container.id})"
    的步骤。使用
    exit
    ,如果命令失败,阶段可以提前停止。
  • 无论退出代码如何,容器都应该停止,因此您应该使用
    try..finally
    块来避免容器泄漏。

总结一下,脚本可能是这样的:

def initialImage = docker.image('${env.IMG_NM}:${env.IMG_TAG}')
def command = "cp ${WORKSPACE}/config.txt /path_to_my_config/config.txt"
try {
    def container = image.run([:], "bash -c '${command}'")

    sh "docker logs -f ${container.id}"
    sh "exit \$(docker wait ${container.id})"

    def finalImageId = sh(
        script: "docker commit ${container.id}",
        returnStdout: true)
    ).trim()

    // here, use finalImageId to add a tag, push to a repository etc.
}
finally {
    container?.stop()
}
© www.soinside.com 2019 - 2024. All rights reserved.