Skip to content

GeorgOfenbeck/mill-docker

Repository files navigation

Mill Docker Jib

1. TL:DR

This is a Mill Plugin to integrate jib

2. Motivation

Mill is an excellent build tool for Scala. It comes with "batteries included" and as such already has a Docker Plugin. So how does this Plugin differ from the out of the box Docker Plugin?

In a nutshell the Mill contrib Docker Plugin is a thin wrapper around the Docker CLI.

Mill Contrib Docker

There are a few reasons why you might want to use Jib instead of writing Dockerfiles:

  • Unlike the contrib Docker Plugin, Jib does not require a Docker daemon to be running. This is particularly useful in CI/CD pipelines.

  • By default the Contrib Plugin creates a "fat jar" and puts it as a single layer in the container. As a consequence the whole container needs to be rebuilt if only a single class file changes.

  • Certain use cases are cumbersome to implement with the contrib plugin (e.g. adding a java agent to the JVM). The build step cannot be easily customized as it is just a thin wrapper. It can easily be replaced with your own build step, but that was the trigger for creating this plugin.

For a detailed introduction to Jib I recommend the following talks:

maxresdefault

maxresdefault

In short Jib:

  • Jib allows you to split your application into multiple layers. This allows for more incremental builds and faster deployments which is very much in the "spirit" of Mill. You only need to rebuild the layer that changed (e.g. only your application code without its dependencies).

  • Jib can pull, build and deploy directly to and from a container registry without the need for a Docker daemon. The local Docker demon or a Tar file can be used as alternative sources/targets.

Mill Docker Jib

3. In Action

This is a terminal recording of the plugin in action - using the dive tool it compares the images created by the contrib Docker Plugin on the left and the Jib Plugin on the right. The example uses libro-finito. It serves as a case study. As you can see the Jib Plugin separates the major size contributors into separate layers. This allows for more incremental builds and faster deployments.

https://github.com/LaurenceWarne/libro-finito

4. Plugin Design

In terms of execution the next graph shows the high level flow of the plugin The source Image is pulled and used as Base Layer. The artifacts from various JavaModule tasks are used to fill the other layers. The layers are used as input for a Java Container Builder.

The user can override the two methods getJavaBuilder, getJibBuilder to customize the behaviour as much as needed. (Marked in the graph as hooks - but in the current version of the code they are simple overrides as shown in the examples) The first one in ideal if the default Jib Java Container Builder is sufficient and only minor modifications are needed. The second one is more powerful as it allows to fully replace the default Jib Java Container Builder with a custom one.

Finally the container is built using the user provided container parameters and pushed to the according target image format (Container Registry, Docker Daemon, Tarball).

Plugin Flow

5. Plugin Configuration

Parameter Type Description Required

sourceImage

com.ofenbeck.mill.docker.JibSourceImage

Source image for the container. Examples of all possible source image types can be found here.

X

targetImage

com.ofenbeck.mill.docker.ImageReference

Target image for the container. Examples of all possible target image types can be found here.

X

labels

Map[String, String]

Labels to add to the Docker image. This and most of the following settings can be found here.

tags

Seq[String]

Tags to add to the Docker image.

jvmOptions

Seq[String]

JVM runtime options for the container.

exposedPorts

Seq[Int]

TCP ports the container will listen to at runtime.

exposedUdpPorts

Seq[Int]

UDP ports the container will listen to at runtime.

envVars

Map[String, String]

Environment variables for the container.

user

Option[String]

User and group to run the container as.

platforms

Set[md.Platform]

Target platforms for the container.

internalImageFormat

md.JibImageFormat

Internal image format to use.

entrypoint

Seq[String]

Entrypoint command for the container.

jibProgramArgs

Seq[String]

Program arguments for the container.

getJibBuilder

Task[JibContainerBuilder]

Method to override to get/modify the JibContainerBuilder before building the container. See the example here.

getJavaBuilder

Task[JavaContainerBuilder]

Method to override to get/modify the JavaContainerBuilder before building the container. See the example here.

6. Examples

All examples are at the same time integration tests and can be found in the mill-docker/test/resources/ folder. Be aware that the examples include the plugin through a test specific mechanism.

If you want to use the code outside replace accordingly.

6.1. All possible input / output image types

See all possible input/output combinations here.

6.2. Simple Input Configuration Example

An example of standard settings you might wanna modify here

6.3. Java Container Builder Hook Example

An example modifying the Java Container Builder here

6.4. Jib Container Builder Hook Example

An example modifying the Jib Container Builder here

6.5. Jib Custom Layer Example (dropping a default layer)

An example modifying the Jib Container Builder here

7. Future Work

  • Jlink support for smaller images

  • Better support for multi module projects (right now the plugin treats them as upstream dependencies - which is not always what you want)

  • Native Image use case investigation

Releases

No releases published

Packages

No packages published