diff --git a/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala index b7c15ced7..fe5b36ab7 100644 --- a/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala @@ -83,6 +83,7 @@ object DockerPlugin extends AutoPlugin { dockerExposedPorts := Seq(), dockerExposedUdpPorts := Seq(), dockerExposedVolumes := Seq(), + dockerBuildxPlatforms := Seq(), dockerLabels := Map(), dockerEnvVars := Map(), dockerRepository := None, @@ -273,11 +274,21 @@ object DockerPlugin extends AutoPlugin { def publishTask = Def.task { val _ = publishLocal.value - val alias = dockerAliases.value val log = streams.value.log - val execCommand = dockerExecCommand.value + val alias = dockerAliases.value + val context = stage.value + val multiplatform = dockerBuildxPlatforms.value.nonEmpty + val execCommand = + if (multiplatform) + dockerExecCommand.value ++ Seq( + "buildx", + "build", + s"--platform=${dockerBuildxPlatforms.value.mkString(",")}", + "--push" + ) ++ dockerBuildOptions.value :+ "." + else dockerBuildCommand.value alias.foreach { aliasValue => - publishDocker(execCommand, aliasValue.toString, log) + publishDocker(context, execCommand, aliasValue.toString, log, multiplatform) } } tag (Tags.Network, Tags.Publish) @@ -377,7 +388,7 @@ object DockerPlugin extends AutoPlugin { } /** - * @param dockerBaseDirectory, the installation directory + * @param dockerBaseDirectory , the installation directory */ private final def makeWorkdir(dockerBaseDirectory: String): CmdLike = Cmd("WORKDIR", dockerBaseDirectory) @@ -705,7 +716,7 @@ object DockerPlugin extends AutoPlugin { log.info(s"Removed image ${tag}") } - def publishDocker(execCommand: Seq[String], tag: String, log: Logger): Unit = { + def publishDocker(context: File, execCommand: Seq[String], tag: String, log: Logger, multiplatform: Boolean): Unit = { val loginRequired = new AtomicBoolean(false) def publishLogger(log: Logger) = @@ -728,11 +739,11 @@ object DockerPlugin extends AutoPlugin { override def buffer[T](f: => T): T = f } - val cmd = execCommand ++ Seq("push", tag) + val cmd = if (multiplatform) execCommand else execCommand ++ Seq("push", tag) log.debug("Executing " + cmd.mkString(" ")) - val ret = sys.process.Process(cmd) ! publishLogger(log) + val ret = sys.process.Process(cmd, context) ! publishLogger(log) if (loginRequired.get) sys.error("""No credentials for repository, please run "docker login"""") diff --git a/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala b/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala index 37f70e4d1..976ac1ebf 100644 --- a/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala +++ b/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala @@ -74,4 +74,6 @@ private[packager] trait DockerKeysEx extends DockerKeys { "Setting to true will cause Docker to bundle a tini in the container, to run as the init process, which is recommended for JVM apps. " + "Requires Docker API version 1.25+" ) + val dockerBuildxPlatforms = + SettingKey[Seq[String]]("dockerBuildxPlatforms", "The docker image platforms for buildx multi-platform build") } diff --git a/test-project-docker/build.sbt b/test-project-docker/build.sbt index a78baf703..fa298560a 100644 --- a/test-project-docker/build.sbt +++ b/test-project-docker/build.sbt @@ -6,3 +6,5 @@ version := "0.1.0" maintainer := "Gary Coady " dockerBaseImage := "openjdk:8-jre-alpine" dockerUpdateLatest := true +dockerBuildxPlatforms := Seq("linux/arm64/v8", "linux/amd64") +dockerUsername := Some("dswiecki") diff --git a/test-project-docker/project/build.properties b/test-project-docker/project/build.properties index 7c58a83ab..9edb75b77 100644 --- a/test-project-docker/project/build.properties +++ b/test-project-docker/project/build.properties @@ -1 +1 @@ -sbt.version=1.2.6 +sbt.version=1.5.4