From 1e5033b46195128cce745bf6486ea6487f4962c6 Mon Sep 17 00:00:00 2001 From: Matt Cengia Date: Fri, 17 Jul 2020 13:33:50 +1000 Subject: [PATCH 1/3] Don't require Gradle to build Docker image Update Dockerfile to use a multi-stage build and run Gradle *within* the builder container, rather than on the host, so the host needn't have Gradle or JDK installed, then copy the build .jar from the builder container into the final container. Update build.gradle's dockerBuild target to not build the jar, but instead do it within the Docker build process. This results in some double-handling because it requires Gradle and JDK both on the host system *and* within the container, and runs two instances of Gradle during the build, but is added for backwards compatibility. The better approach (rather than running `./gradlew dockerBuild`) is to manually run `docker build -t ma1ua/ma1sd .`. I've tested this process on both a Debian amd64 system and a Raspberry Pi 3 running Raspbian, and it seems to work (though the RPi is pretty slow). --- Dockerfile | 10 +++++++++- build.gradle | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8a38986..5289b04 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,11 @@ +FROM openjdk:8-jre-alpine AS builder + +RUN apk update && apk add gradle git && rm -rf /var/lib/apk/* /var/cache/apk/* + +WORKDIR /ma1sd +COPY . . +RUN ./gradlew shadowJar + FROM openjdk:8-jre-alpine RUN apk update && apk add bash && rm -rf /var/lib/apk/* /var/cache/apk/* @@ -15,4 +23,4 @@ CMD [ "/start.sh" ] ADD src/docker/start.sh /start.sh ADD src/script/ma1sd /app/ma1sd -ADD build/libs/ma1sd.jar /app/ma1sd.jar +COPY --from=builder /ma1sd/build/libs/ma1sd.jar /app/ma1sd.jar diff --git a/build.gradle b/build.gradle index fa081b2..bed09a6 100644 --- a/build.gradle +++ b/build.gradle @@ -264,7 +264,7 @@ task debBuild(dependsOn: shadowJar) { } } -task dockerBuild(type: Exec, dependsOn: shadowJar) { +task dockerBuild(type: Exec) { commandLine 'docker', 'build', '-t', dockerImageTag, project.rootDir doLast { From a1ab1e8e0ae790c7b3a41a985c521bf4e3acdff5 Mon Sep 17 00:00:00 2001 From: Matt Cengia Date: Fri, 17 Jul 2020 13:35:54 +1000 Subject: [PATCH 2/3] Tidy Gradle dockerBuildX target Build linux/amd64, linux/arm64, and linux/arm/v7 (arm 32-bit) targets all at once. This still requires Gradle and JDK on the local machine (i.e. outside of the Docker build container), because it seems pointless to build the .jar 3 times, once for each architecture, but tags all the images with the same tag, rather than using a tag for each architecture. This allows clients to all use the same image tag, but pull down the architecture that's right for them. I'd like to have it build the .jar file in a container (so the host doesn't need JDK and Gradle), but couldn't think how to do that efficiently (i.e. only once), with this approach. --- build.gradle | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index bed09a6..5b1185c 100644 --- a/build.gradle +++ b/build.gradle @@ -275,22 +275,10 @@ task dockerBuild(type: Exec) { } task dockerBuildX(type: Exec, dependsOn: shadowJar) { - commandLine 'docker', 'buildx', 'build', '--load', '--platform', 'linux/arm64', '-t', dockerImageTag + '-arm64', project.rootDir + commandLine 'docker', 'buildx', 'build', '--push', '--platform', 'linux/arm64,linux/amd64,linux/arm/v7', '-t', dockerImageTag , project.rootDir doLast { exec { - commandLine 'docker', 'buildx', 'build', '--load', '--platform', 'linux/amd64', '-t', dockerImageTag + '-amd64', project.rootDir - } - - exec { - commandLine 'docker', 'tag', dockerImageTag + '-arm64', "${dockerImageName}:latest-arm64-dev" - } - - exec { - commandLine 'docker', 'tag', dockerImageTag + '-amd64', "${dockerImageName}:latest-amd64-dev" - } - - exec { - commandLine 'docker', 'tag', dockerImageTag + '-amd64', "${dockerImageName}:latest-dev" + commandLine 'docker', 'buildx', 'build', '--push', '--platform', 'linux/arm64,linux/amd64,linux/arm/v7', '-t', "${dockerImageName}:latest-dev", project.rootDir } } } From 1480507d76cebffb44d6689c1297233b25a09c45 Mon Sep 17 00:00:00 2001 From: Matt Cengia Date: Fri, 18 Sep 2020 12:45:33 +1000 Subject: [PATCH 3/3] Only build .jar on current build platform Because the .jar is platform-independent, we don't need to build it for every architecture. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5289b04..6eb75f4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:8-jre-alpine AS builder +FROM --platform=$BUILDPLATFORM openjdk:8-jre-alpine AS builder RUN apk update && apk add gradle git && rm -rf /var/lib/apk/* /var/cache/apk/*