我目前正在写一份作业,将上游Docker映像克隆到我的内部Docker存储库中。 我的工作参数页面看起来像
因此,它将获取所有图像,然后生成实际外观的路径
pipeline {
agent none
stages {
stage('Create new image paths:tag'){
steps {
script {
params.IMAGES.split("\\r?\\n").each{ oldfullPath ->
def (path, tag) = oldfullPath.tokenize( ':' )
def app = path.tokenize('/')[-1]
println "App is ${app} and Tag is ${tag}"
switch(params.REPO) {
case "monitoring":
image = "eu.gcr.io/<PROJECT>/infra/monitoring"
break
case "apps":
image = "eu.gcr.io/<PROJECT>/infra/apps"
break
}
def newFullPath = "${image}/${app}:${tag}"
println "Full old image path is ${oldfullPath}"
println "Full new image path is ${newFullPath}"
// Pull and Push Image stage should be called here ! Using `${oldfullPath}` and `${newFullPath}`
}
}
}
}
如您所见,由于我有多行输入,因此必须使用循环遍历每一行,获取应用程序名称和标记,然后使用switch
生成newpath。因此,对于每次迭代,我得到${oldfullPath}
和${newfullPath}
现在,我需要拉动这些docker镜像。我不想利用dind
,所以我正在使用Kaniko。而要拉动图像,我可以使用类似这样的东西:
stage('Pull and Push Image') {
agent {
label "kaniko"
}
steps {
container(name: 'kaniko', shell: '/busybox/sh') {
withCredentials([
string(credentialsId: 'infra', variable: 'PASS')
]) {
withEnv(['PATH+EXTRA=/busybox:/kaniko']) {
sh """#!/busybox/sh
echo "FROM <OLD-IMAGE-PATH-COMES-HERE>" | \
/kaniko/executor \
--dockerfile /dev/stdin \
--destination <NEW-IMAGE-PATH-COMES-HERE>
"""
}
}
}
}
}
如您所见,这是一个完全不同的阶段。因此,我不确定如何从上一阶段重复调用Pull and Push Image
阶段。任何帮助将不胜感激。
答案 0 :(得分:0)
这里有很多事情要处理。
首先,如果您只想将Docker映像复制到注册表中,可以按照以下步骤进行操作:
me@vm:~$ docker pull alpine:latest
latest: Pulling from library/alpine
89d9c30c1d48: Pull complete
Digest: sha256:c19173c5ada610a5989151111163d28a67368362762534d8a8121ce95cf2bd5a
Status: Downloaded newer image for alpine:latest
me@vm:~$ docker tag alpine:latest my-registry.my-company.io/alpine:latest
me@vm:~$ docker push my-registry.my-company.io/alpine:latest
The push refers to a repository [my-registry.my-company.io/alpine]
77cae8ab23bf: Pushed
latest: digest: sha256:e4355b66995c96b4b468159fc5c7e3540fcef961189ca13fee877798649f531a size: 528
第二,您可以在循环中的容器内完成解析,而不是在单独的步骤中进行
stage('Pull and Push Image') {
agent {
label "kaniko"
}
steps {
container(name: 'kaniko', shell: '/busybox/sh') {
withCredentials([
string(credentialsId: 'infra', variable: 'PASS')
]) {
withEnv(['PATH+EXTRA=/busybox:/kaniko']) {
// RUN THE LOOP HERE
script {
params.IMAGES.split("\\r?\\n").each{ oldfullPath ->
def (path, tag) = oldfullPath.tokenize( ':' )
def app = path.tokenize('/')[-1]
println "App is ${app} and Tag is ${tag}"
switch(params.REPO) {
case "monitoring":
image = "eu.gcr.io/<PROJECT>/infra/monitoring"
break
case "apps":
image = "eu.gcr.io/<PROJECT>/infra/apps"
break
}
def newFullPath = "${image}/${app}:${tag}"
println "Full old image path is ${oldfullPath}"
println "Full new image path is ${newFullPath}"
sh """#!/busybox/sh
echo "FROM ${oldfullPath}" | \
/kaniko/executor \
--dockerfile /dev/stdin \
--destination ${newFullPath}
"""
// adjust closing brackets as needed
这当然会在单个节点上按顺序运行建筑物,这可能对您来说还可以,或者可能不行。
现在,让我们假设您真正的问题是,“如何在声明式管道中启动未知数量的并行阶段?”
答案是,您可以以编程方式构建管道,如下所示:
images_array = ["quay.io/one", "docker.io/two", "docker.io/three"] // or split params as needed
def getBuilders()
{
def builders = [:]
images_array.eachWithIndex { it, index ->
// name the stage
def name = 'Build image #' + (index + 1)
builders[name] = {
stage (name) {
def my_label = "kaniko" // can choose programmatically if needed
node(my_label) {
timeout(time: 2, unit: 'HOURS') {
try {
buildOneImage(it)
}
catch (err) { println "Failed to build ${it}"; throw err }
finally { }
}
}
}
}
};
return builders
}
def buildOneImage(old_path) {
// replace path as needed, build image
// use scripted-style pipeline, not the declarative one
}
然后在您的主管道中
stage('Build all images') {
steps {
script {
def builders = getBuilders()
parallel builders
}
}