From d50190110327e68f367509ae3b76057fd933f637 Mon Sep 17 00:00:00 2001 From: Martin Egri Date: Mon, 11 Mar 2024 16:21:49 +0100 Subject: [PATCH 1/3] Add 'jvmArgs' option to docker contrib configuration. --- .../mill/contrib/docker/DockerModule.scala | 6 ++++- .../contrib/docker/DockerModuleTest.scala | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/contrib/docker/src/mill/contrib/docker/DockerModule.scala b/contrib/docker/src/mill/contrib/docker/DockerModule.scala index af7562f8db9..0125f0fba17 100644 --- a/contrib/docker/src/mill/contrib/docker/DockerModule.scala +++ b/contrib/docker/src/mill/contrib/docker/DockerModule.scala @@ -18,6 +18,7 @@ trait DockerModule { outer: JavaModule => def labels: T[Map[String, String]] = Map.empty[String, String] def baseImage: T[String] = "gcr.io/distroless/java:latest" def pullBaseImage: T[Boolean] = T(baseImage().endsWith(":latest")) + def jvmArgs: T[Seq[String]] = Seq.empty[String] /** * TCP Ports the container will listen to at runtime. @@ -113,11 +114,14 @@ trait DockerModule { outer: JavaModule => if (user().isEmpty) "" else s"USER ${user()}" ).filter(_.nonEmpty).mkString(sys.props("line.separator")) + val quotedEntryPointArgs = (Seq("java") ++ jvmArgs() ++ Seq("-jar", s"/$jarName")) + .map(arg => s"\"$arg\"").mkString(", ") + s""" |FROM ${baseImage()} |$lines |COPY $jarName /$jarName - |ENTRYPOINT ["java", "-jar", "/$jarName"]""".stripMargin + |ENTRYPOINT [$quotedEntryPointArgs]""".stripMargin } final def build = T { diff --git a/contrib/docker/test/src/mill/contrib/docker/DockerModuleTest.scala b/contrib/docker/test/src/mill/contrib/docker/DockerModuleTest.scala index b7db161c5ee..7e1ebdaaff4 100644 --- a/contrib/docker/test/src/mill/contrib/docker/DockerModuleTest.scala +++ b/contrib/docker/test/src/mill/contrib/docker/DockerModuleTest.scala @@ -36,6 +36,11 @@ object DockerModuleTest extends TestSuite { override def user = "user1" override def executable = testExecutable } + + object dockerJvmArgs extends DockerConfig { + override def executable = testExecutable + override def jvmArgs = Seq("-Xmx1024M") + } } val testArtifactName = "mill-docker-contrib-test" @@ -132,6 +137,23 @@ object DockerModuleTest extends TestSuite { ) assert(dockerfileStringRefined == expected) } + + "extra jvm args" - { + val eval = new TestEvaluator(Docker) + val Right((dockerfileString, _)) = eval(Docker.dockerJvmArgs.dockerfile) + val expected = multineRegex.replaceAllIn( + """ + |FROM gcr.io/distroless/java:latest + |COPY out.jar /out.jar + |ENTRYPOINT ["java", "-Xmx1024M", "-jar", "/out.jar"]""".stripMargin, + sys.props("line.separator") + ) + val dockerfileStringRefined = multineRegex.replaceAllIn( + dockerfileString, + sys.props("line.separator") + ) + assert(dockerfileStringRefined == expected) + } } } } From 655dc4ad5990f58b362c3d194732f466e432cd66 Mon Sep 17 00:00:00 2001 From: Martin Egri Date: Mon, 11 Mar 2024 16:26:43 +0100 Subject: [PATCH 2/3] Rename 'jvmArgs' -> 'jvmOptions' --- contrib/docker/src/mill/contrib/docker/DockerModule.scala | 4 ++-- .../test/src/mill/contrib/docker/DockerModuleTest.scala | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contrib/docker/src/mill/contrib/docker/DockerModule.scala b/contrib/docker/src/mill/contrib/docker/DockerModule.scala index 0125f0fba17..7d1a2a116d0 100644 --- a/contrib/docker/src/mill/contrib/docker/DockerModule.scala +++ b/contrib/docker/src/mill/contrib/docker/DockerModule.scala @@ -18,7 +18,7 @@ trait DockerModule { outer: JavaModule => def labels: T[Map[String, String]] = Map.empty[String, String] def baseImage: T[String] = "gcr.io/distroless/java:latest" def pullBaseImage: T[Boolean] = T(baseImage().endsWith(":latest")) - def jvmArgs: T[Seq[String]] = Seq.empty[String] + def jvmOptions: T[Seq[String]] = Seq.empty[String] /** * TCP Ports the container will listen to at runtime. @@ -114,7 +114,7 @@ trait DockerModule { outer: JavaModule => if (user().isEmpty) "" else s"USER ${user()}" ).filter(_.nonEmpty).mkString(sys.props("line.separator")) - val quotedEntryPointArgs = (Seq("java") ++ jvmArgs() ++ Seq("-jar", s"/$jarName")) + val quotedEntryPointArgs = (Seq("java") ++ jvmOptions() ++ Seq("-jar", s"/$jarName")) .map(arg => s"\"$arg\"").mkString(", ") s""" diff --git a/contrib/docker/test/src/mill/contrib/docker/DockerModuleTest.scala b/contrib/docker/test/src/mill/contrib/docker/DockerModuleTest.scala index 7e1ebdaaff4..3fe71603886 100644 --- a/contrib/docker/test/src/mill/contrib/docker/DockerModuleTest.scala +++ b/contrib/docker/test/src/mill/contrib/docker/DockerModuleTest.scala @@ -37,9 +37,9 @@ object DockerModuleTest extends TestSuite { override def executable = testExecutable } - object dockerJvmArgs extends DockerConfig { + object dockerJvmOptions extends DockerConfig { override def executable = testExecutable - override def jvmArgs = Seq("-Xmx1024M") + override def jvmOptions = Seq("-Xmx1024M") } } @@ -138,9 +138,9 @@ object DockerModuleTest extends TestSuite { assert(dockerfileStringRefined == expected) } - "extra jvm args" - { + "extra jvm options" - { val eval = new TestEvaluator(Docker) - val Right((dockerfileString, _)) = eval(Docker.dockerJvmArgs.dockerfile) + val Right((dockerfileString, _)) = eval(Docker.dockerJvmOptions.dockerfile) val expected = multineRegex.replaceAllIn( """ |FROM gcr.io/distroless/java:latest From e04066bc4eaf94d5c65f098c3b8aa94f2c1d70d0 Mon Sep 17 00:00:00 2001 From: Martin Egri Date: Mon, 11 Mar 2024 22:28:20 +0100 Subject: [PATCH 3/3] Add documentation. --- contrib/docker/readme.adoc | 2 ++ .../docker/src/mill/contrib/docker/DockerModule.scala | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/contrib/docker/readme.adoc b/contrib/docker/readme.adoc index 449546f9747..b12f8d5327e 100644 --- a/contrib/docker/readme.adoc +++ b/contrib/docker/readme.adoc @@ -53,6 +53,8 @@ object docker extends DockerConfig { def volumes = Seq("/v1", "/v2") // Environment variables to be set in the container (ENV instructions) def envVars = Map("foo" -> "bar", "foobar" -> "barfoo") + // JVM runtime options such as heap size settings + def jvmOptions = Seq("-Xmx1024M", "-XX:+HeapDumpOnOutOfMemoryError") // Add RUN instructions def run = Seq( "/bin/bash -c 'echo Hello World!'", diff --git a/contrib/docker/src/mill/contrib/docker/DockerModule.scala b/contrib/docker/src/mill/contrib/docker/DockerModule.scala index 7d1a2a116d0..bc6da6c4f4a 100644 --- a/contrib/docker/src/mill/contrib/docker/DockerModule.scala +++ b/contrib/docker/src/mill/contrib/docker/DockerModule.scala @@ -18,6 +18,15 @@ trait DockerModule { outer: JavaModule => def labels: T[Map[String, String]] = Map.empty[String, String] def baseImage: T[String] = "gcr.io/distroless/java:latest" def pullBaseImage: T[Boolean] = T(baseImage().endsWith(":latest")) + + /** + * JVM runtime options. Each item of the Seq should consist of an option and its desired value, like + * {{{ + * def jvmOptions = Seq("-Xmx1024M", "-agentlib:jdwp=transport=dt_socket,server=y,address=8000", …) + * }}} + * For a full list of options consult the official documentation at + * [[https://docs.oracle.com/en/java/javase/21/docs/specs/man/java.html#overview-of-java-options]] + */ def jvmOptions: T[Seq[String]] = Seq.empty[String] /**