{"id":17835005,"url":"https://github.com/carlosedp/mill-docker-nativeimage","last_synced_at":"2025-03-19T14:31:36.321Z","repository":{"id":65507527,"uuid":"551079156","full_name":"carlosedp/mill-docker-nativeimage","owner":"carlosedp","description":"A Scala Mill plugin to build container images with Native Image (GraalVM Binaries) application","archived":false,"fork":false,"pushed_at":"2025-02-26T18:13:21.000Z","size":174,"stargazers_count":17,"open_issues_count":7,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-26T19:25:55.807Z","etag":null,"topics":["docker","graalvm","graalvm-native-image","mill","mill-plugin","native-image","scala"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/carlosedp.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"carlosedp","patreon":"carlosedp"}},"created_at":"2022-10-13T20:05:05.000Z","updated_at":"2025-02-26T18:13:25.000Z","dependencies_parsed_at":"2023-11-13T13:44:24.353Z","dependency_job_id":"66fa26dc-d749-4b42-a156-b9e23b3d5ea0","html_url":"https://github.com/carlosedp/mill-docker-nativeimage","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosedp%2Fmill-docker-nativeimage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosedp%2Fmill-docker-nativeimage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosedp%2Fmill-docker-nativeimage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carlosedp%2Fmill-docker-nativeimage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/carlosedp","download_url":"https://codeload.github.com/carlosedp/mill-docker-nativeimage/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243997108,"owners_count":20380980,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","graalvm","graalvm-native-image","mill","mill-plugin","native-image","scala"],"created_at":"2024-10-27T20:16:10.691Z","updated_at":"2025-03-19T14:31:36.312Z","avatar_url":"https://github.com/carlosedp.png","language":"Scala","funding_links":["https://github.com/sponsors/carlosedp","https://patreon.com/carlosedp"],"categories":[],"sub_categories":[],"readme":"# mill-docker-nativeimage\n\nThis is a [Mill][mill] plugin modeled after the [contrib][docker-plugin] Docker plugin which allows building Docker images with Native Image binaries built by the amazing plugin [mill-native-image][mill-native-image] by Alex Archambault.\n\nThe inspiration came from Quarkus framework which generates applications that are cloud native and \"Container-ready\" with fast startup times and small size not depending on the JVM.\n\nThe plugin allows building very small containers and the application packed as a binary produces blazing fast startup times.\n\nAs a comparison, below the start time for the same application packed in an assembly with it's JAR using a JDK image compared to the native binary built with GraalVM in a Ubuntu image:\n\n```plain\n# Native Image\n❯ date +%Y-%m-%dT%H:%M:%S.%N \u0026\u0026 docker run -it -p 8080:8080 --rm carlosedp/zioscalajs-backend-native\n2023-02-03T14:30:06.536864570\n{\"timestamp\":\"2023-02-03T14:30:07.177923Z     \",\"level\":\"INFO\",\"thread\":\"zio-fiber-6\",\"message\":\"Server started at http://localhost:8080\"}\n{\"timestamp\":\"2023-02-03T14:30:07.178301Z     \",\"level\":\"INFO\",\"thread\":\"zio-fiber-6\",\"message\":\"Started gaugetest with random Double every second\"}\n\n# JDK\n❯ date +%Y-%m-%dT%H:%M:%S.%N \u0026\u0026 docker run -it -p 8080:8080 --rm carlosedp/zioscalajs-backend-jdk\n2023-02-03T14:30:14.004191633\n{\"timestamp\":\"2023-02-03T14:30:16.548346423Z  \",\"level\":\"INFO\",\"thread\":\"zio-fiber-6\",\"message\":\"Server started at http://localhost:8080\"}\n{\"timestamp\":\"2023-02-03T14:30:16.698928238Z  \",\"level\":\"INFO\",\"thread\":\"zio-fiber-6\",\"message\":\"Started gaugetest with random Double every second\"}\n```\n\nAs seen, the native version starts in 0,64105843 seconds versus 2,54415479 from the JDK version from launch to the first log message.\n\n## Getting Started\n\nThe plugin provides a trait to configure the native build and container image, in addition there are two commands, one for building the Docker image and another to push the image to the registry. To push the image, the container runtime (Docker) must be already authenticated in your registry or DockerHub.\n\n### Installing the Plugin\n\nTo start using this plugin you'll want to include the following import in your build file:\n\n```scala\nimport $ivy.`com.carlosedp::mill-docker-nativeimage::0.6.2`  //ReleaseVerMill\nimport com.carlosedp.milldockernative.DockerNative\n```\n\nUnder the hood, the plugin uses [mill-native-image][mill-native-image] to build your application Native Image binary which gets copied into the base container image which can be customized with some parameters as listed below. To generate the Native Image, you need an installed version of [GraalVM][graalvm-install] and the native-image utility.\n\n### Usage\n\nSample configuration:\n\n```scala\nimport mill._, mill.scalalib._, mill.scalalib.scalafmt._\nimport $ivy.`com.carlosedp::mill-docker-nativeimage::0.6.1`\nimport com.carlosedp.milldockernative.DockerNative\n\nobject hello extends ScalaModule with DockerNative {\n  def scalaVersion = \"3.3.1\"\n  // def ivyDeps = ...\n//   def nativeImageClassPath = runClasspath()\n  object dockerNative extends DockerNativeConfig {\n    // Native Image parameters\n    def nativeImageName         = \"hello\"\n    def nativeImageGraalVmJvmId = T(\"graalvm-java17:22.3.2\")\n    def nativeImageClassPath    = runClasspath()\n    def nativeImageMainClass    = \"com.domain.Hello.Hello\"\n    // GraalVM parameters depending on your application needs\n    def nativeImageOptions = Seq(\n      \"--no-fallback\",\n      \"--enable-url-protocols=http,https\",\n      \"-Djdk.http.auth.tunneling.disabledSchemes=\",\n    ) ++ (if (sys.props.get(\"os.name\").contains(\"Linux\")) Seq(\"--static\") else Seq.empty)\n\n    // Docker image parameters\n    def baseImage    = \"ubuntu:22.04\"\n    def tags         = List(\"docker.io/myuser/helloapp\")\n    def exposedPorts = Seq(8080)\n  }\n\n  object test extends Tests {\n    // ...\n  }\n}\n```\n\nBuild and Push with:\n\n```sh\nmill hello.dockerNative.build\n\n# Test run\ndocker run -it --rm docker.io/myuser/helloapp\n\n# Push to a registry\nmill hello.dockerNative.push\n```\n\nA sample project is provided in [./example](./example) where above commands work.\n\nIf only the GraalVM native image binary is required to be built on a Docker container (for Linux), there is a convenience task:\n\n```sh\nmill hello.dockerNative.buildBin\n```\n\nA more detailed build for a ZIO-http sample application with Native, Docker and DockerNative builds can be seen at the [zio-scalajs-stack][zio-scalajs-stack-build] project. Running a Native Image binary for a Scala 3 project requires Scala 3.3 due to a bug described [here][nativeimage-bug].\n\n### Configuration\n\nImage configuration parameters defined in `DockerNativeConfig` trait:\n\n```scala\n//\n// These are the parameters to customize the image used to build the GraalVM Native Image binary\n//\n// Version of Coursier to be used to pull Scala dependencies in the build image\ndef coursierVersion: T[String] = \"v2.1.6\"\n// Override the name of the image that will be generated to build the GraalVM Native Image\ndef baseDockerImage: T[String] = \"mybasebuild\"\n// Override the DockerFile used to build the GraalVM Native Image\ndef baseDockerFile: T[String] = s\"\"\"FROM IMAGE:VERSION...\"\"\"\n//\n// These are the parameters to customize the output container image with the application\n//\n// Override tags to set the output image name\ndef tags = List(\"docker.io/myuser/myApp\")\n// Overrides base container image, default value below\ndef baseImage = \"redhat/ubi8\"\n// Configure whether the docker build should check the remote registry for a new version of the base image before building.\n// By default this is true if the base image is using a latest tag\ndef pullBaseImage = true\n// Add container metadata via the LABEL instruction\ndef labels = Map(\"version\" -\u003e \"1.0\")\n// TCP ports the container will listen to\ndef exposedPorts = Seq(8080, 443)\n// UDP ports the container will listen to\ndef exposedUdpPorts = Seq(80)\n// The names of mount points, these will be translated to VOLUME instructions\ndef volumes = Seq(\"/v1\", \"/v2\")\n// Environment variables to be set in the container (ENV instructions)\ndef envVars = Map(\"foo\" -\u003e \"bar\", \"foobar\" -\u003e \"barfoo\")\n// Command line arguments to be passed to the executable\ndef commandArgs = Seq(\"--port=80\", \"-v\")\n// Add RUN instructions\ndef run = Seq(\n  \"/bin/bash -c 'echo Hello World!'\",\n  \"useradd -ms /bin/bash new-user\"\n)\n// User to use when running the image\ndef user = \"nobody\"\n// Optionally override the docker executable to use something else\ndef executable = \"podman\"\n```\n\nNative Image parameters:\n\n```scala\n// Define the output binary name\ndef nativeImageName = \"myAppName\"\n// Set the GraalVM version\ndef nativeImageGraalVmJvmId = T {\"graalvm-java17:22.3.1\"}\n// Define the classpath\ndef nativeImageClassPath = runClasspath()\n// Define your application main class\ndef nativeImageMainClass = \"com.domain.myClass\"\n// Sets GraalVM Native Image options, depends on your application uses\ndef nativeImageOptions = Seq(\n  \"--no-fallback\",\n)\n```\n\nFor more details, check the [mill-native-image][mill-native-image-src] source code where all available options is shown.\n\n## Acknowledgements\n\nThis plugin would not be possible without the amazing work in the [mill-docker-plugin][docker-plugin] and [mill-native-image][mill-native-image] plugins.\n\n\n[mill]: https://com-lihaoyi.github.io/mill/mill/Intro_to_Mill.html\n[docker-plugin]: https://com-lihaoyi.github.io/mill/mill/Plugin_Docker.html\n[mill-native-image]: https://github.com/alexarchambault/mill-native-image\n[mill-native-image-src]: https://github.com/alexarchambault/mill-native-image/blob/master/plugin/src/io/github/alexarchambault/millnativeimage/NativeImage.scala\n[graalvm-install]: https://www.graalvm.org/22.1/reference-manual/native-image/\n[zio-scalajs-stack-build]: https://github.com/carlosedp/zio-scalajs-stack/blob/5c9e2817480ba7ef263770108197a36ff493dea7/build.sc#L51\n[nativeimage-bug]: https://github.com/carlosedp/zio-scalajs-stack/issues/8\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlosedp%2Fmill-docker-nativeimage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcarlosedp%2Fmill-docker-nativeimage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarlosedp%2Fmill-docker-nativeimage/lists"}