我有一个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 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()
}