我正在使用docker插件构建我的docker映像, 我有一个包含multiple services的项目,但它是一个monolete,所以我只有一个build.gradle文件。 我要尝试的是使用地图循环构建所有图像, 但是在构建项目时,只会构建地图中的最后一个元素。
这些是 build.gradle 文件的相关部分:
plugins {
id 'java'
id 'application'
id 'maven'
id 'distribution'
id 'maven-publish'
//docker-plugin
id 'com.palantir.docker' version '0.25.0'
}
group = 'com.company.scheduler'
version '4.0.0-SNAPSHOT'
//Handle release version scenario
def PublishedVersion
def buildNumber
if (version ==~ /(?s).*SNAPSHOT.*/) { //Check if SNAPSHOT/Release version
if ("$System.env.BUILD_NUMBER" == null) {buildNumber = '0'} else {buildNumber = "$System.env.BUILD_NUMBER"}
PublishedVersion = version
} else {
if ("$System.env.BUILD_NUMBER" == null) {buildNumber = '0'} else {buildNumber = "$System.env.BUILD_NUMBER"}
PublishedVersion = version + '-' + buildNumber
}
mainClassName = 'com.company.scheduler'
dependencies {
compile group: 'com.coralogix.sdk', name: 'coralogix-sdk', version: '2.0.3'
}
def serviceOptionMap = [ "utility-meters": "utility_meters_import_plugins",
"weather": "weather_importer"
]
serviceOptionMap.each { k, v ->
docker {
def service_id="${k}"
def artifact_start_script="${v}"
println 'artifact_start_script: ' + artifact_start_script
println 'service_id: ' + service_id
name "47957039666.dkr.ecr.us-east-1.amazonaws.com/panpwr/service-gradle/${service_id}:$PublishedVersion"
//if (version ==~ /(?s).*SNAPSHOT.*/) {tag "$version", "47957039666.dkr.ecr.us-east-1.amazonaws.com/panpwr/ev/${project.name}:latest"}
copySpec.from("build/distributions").into(".")
dockerfile file("${rootProject.projectDir}/Dockerfile")
buildArgs([ARTIFACT_ID: "${service_id}", PANPWR_VERSION: "$PublishedVersion", ARTIFACT_START_SCRIPT: "$artifact_start_script"])
labels(["service-name": "${service_id}", "service-version": "$PublishedVersion"])
pull false //TODO: change to true
noCache false
println 'built docker image: ' + service_id
}
}
这是构建输出:
> Configure project :scheduled-tasks
artifact_start_script: utility_meters_import_plugins
service_id: utility-meters
built docker image: utility-meters
artifact_start_script: weather_importer
service_id: weather
built docker image: weather
> Task :scheduled-tasks:dockerClean
> Task :scheduled-tasks:dockerPrepare
> Task :scheduled-tasks:docker
BUILD SUCCESSFUL in 5s
3 actionable tasks: 3 executed
10:16:39 AM: Task execution finished 'docker'.
当我查看本地图像时,我只能看到第二张图像:
$ docker images | grep gradle
47957039666.dkr.ecr.us-east-1.amazonaws.com/panpwr/service-gradle/weather 4.0.0-SNAPSHOT 729a926206ed 20 hours ago 1.11GB
答案 0 :(得分:1)
这是对Gradle运作方式的常见误解。虽然以强制性方式(例如常见的Groovy脚本)评估了实际的构建脚本,但是任务概念还是声明性的:
Gradle区分配置阶段和执行阶段。在配置阶段期间,将评估构建脚本并配置任务。在执行阶段,将执行所有必需的任务。必需的任务是使用命令行及其(传递)依赖项指定的任务。
当构建脚本作者使用println
来了解任务的执行方式,但是所有println
语句都是在配置阶段进行评估时,这种误解通常会变得很明显。
让我们看看您的具体问题。您有一个循环,在该循环内,您有类似docker { ... }
的内容。标题中显示“正在Map循环中运行gradle任务”,因此您认为docker { ... }
运行任务,但这是不正确的。没错,docker
在您的示例中是一个任务,但是您的代码不会运行(或执行)该任务,而您的代码只是配置了该任务。评估构建脚本后,Gradle将根据所有任务及其配置的任务依赖项(dependsOn
语句)设置任务图。使用此任务图,Gradle将确定所需的任务并执行它们。
现在,知道任务docker
并未执行而是仅已配置,因此您的代码问题非常明显:任务的第二个配置将覆盖第一个配置。顺便说一下,这与循环无关,您可以随后应用这两种配置并获得相同的结果:
docker {
name "first"
dockerfile file("first/Dockerfile")
}
docker {
name "second"
dockerfile file("second/Dockerfile")
}
您的方法的实际问题却完全不同:在Gradle中,每个任务在构建中将仅被执行一次一次。这意味着,您将无法运行任务docker
两次以创建两个Docker映像。您要么需要配置任务,以便它在一次执行中创建两个docker映像,要么以某种方式生成相同类型的两个不同任务。我不熟悉您使用的插件,因此不知道它是否可以使用这两种方法之一。
您可以看看本杰明·穆奇科(Benjamin Muschko)的Gradle Docker Plugin,您可以根据需要创建任意数量的DockerBuildImage
类型的任务。
答案 1 :(得分:0)
事实证明,此插件doesn't support building multiple images, 因此,我最终为每个服务创建了一个子模块,该子模块仅使用此插件创建docker映像。 因此,这几乎是结构:
├── Dockerfile
├── app1
│ └── build.gradle
├── app2
│ └── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle-user-home
├── gradlew
├── build.gradle
这是子模块的简单 gradle.build :
plugins {
//docker-plugin
id 'com.palantir.docker' version '0.25.0'
}
version '4.0.0-SNAPSHOT'
//Handle release version scenario
def PublishedVersion
def buildNumber
if (version ==~ /(?s).*SNAPSHOT.*/) { //Check if SNAPSHOT/Release version
if ("$System.env.BUILD_NUMBER" == null) {buildNumber = '0'} else {buildNumber = "$System.env.BUILD_NUMBER"}
PublishedVersion = version
} else {
if ("$System.env.BUILD_NUMBER" == null) {buildNumber = '0'} else {buildNumber = "$System.env.BUILD_NUMBER"}
PublishedVersion = version + '-' + buildNumber
}
docker {
name "47957039666.dkr.ecr.us-east-1.amazonaws.com/panpwr/service-gradle/${project.name}:$PublishedVersion"
copySpec.from("${rootProject.projectDir}/scheduled-tasks/build/distributions").into(".")
dockerfile file("${rootProject.projectDir}/Dockerfile")
buildArgs([ARTIFACT_ID: "${project.name}", PANPWR_VERSION: "$PublishedVersion", ARTIFACT_START_SCRIPT: "${project.name}"])
labels(["service-name": "${project.name}", "service-version": "$PublishedVersion"])
pull true
noCache false
println 'built docker image: ' + project.name
}
publishing {
publications {
dockerPublication(MavenPublication) {
from components.docker
artifactId project.name + "-docker"
}
}
}
在根项目上运行docker任务会创建所有docker映像:
./gradlew clean build docker -g gradle-user-home