sbt-docker is a sbt plugin which creates Docker images with your artifacts.
- sbt
- Docker
Add sbt-docker as a dependency in project/plugins.sbt
:
addSbtPlugin("se.marcuslonnberg" % "sbt-docker" % "0.5.2")
Start by adding the following to your build.sbt
file:
import DockerKeys._
dockerSettings
// add your sbt-docker settings here
This sets up some settings with default values and adds the docker
task which builds the Docker image.
The only setting that is left for you to define is dockerfile in docker
.
Typically you rely on some sbt task to generate one or several artifacts that you want inside your Docker image.
For example the package
task could be used to generate JAR files, or tasks from plugins such as sbt-assembly
.
In those cases you may want to set the docker
task to depend on those other tasks.
So that the artifacts are always up to date when building a Docker image.
Here is how to make the docker task depend on the sbt package
task:
docker <<= docker.dependsOn(Keys.`package`.in(Compile, packageBin))
In order to produce a Docker image a Dockerfile must be defined.
It should be defined at the dockerfile in docker
key.
There is a mutable and an immutable Dockerfile class available, both provides a DSL which resembles the plain text Dockerfile format.
The mutable class is default and is used in the examples below.
Example with the sbt package
task.
import DockerKeys._
import sbtdocker.mutable.Dockerfile
dockerfile in docker := {
val jarFile = artifactPath.in(Compile, packageBin).value
val classpath = (managedClasspath in Compile).value
val mainclass = mainClass.in(Compile, packageBin).value.getOrElse(sys.error("Expected exactly one main class"))
val jarTarget = s"/app/${jarFile.getName}"
// Make a colon separated classpath with the JAR file
val classpathString = classpath.files.map("/app/" + _.getName)
.mkString(":") + ":" + jarTarget
new Dockerfile {
// Base image
from("dockerfile/java")
// Add all files on the classpath
classpath.files.foreach { file =>
add(file, "/app/")
}
// Add the JAR file
add(jarFile, jarTarget)
// On launch run Java with the classpath and the main class
entryPoint("java", "-cp", classpathString, mainclass)
}
}
Example with the sbt-assembly plugin:
import AssemblyKeys._
import DockerKeys._
import sbtdocker.mutable.Dockerfile
dockerSettings
assemblySettings
// Make the docker task depend on the assembly task, which generates a fat JAR file
docker <<= (docker dependsOn assembly)
dockerfile in docker := {
val artifact = (outputPath in assembly).value
val artifactTargetPath = s"/app/${artifact.name}"
new Dockerfile {
from("dockerfile/java")
add(artifact, artifactTargetPath)
entryPoint("java", "-jar", artifactTargetPath)
}
}
Have a look at DockerfileExamples for different ways of defining a Dockerfile.
To build an image use the docker
task.
Simply run sbt docker
from your prompt or docker
in the sbt console.
An image that have already been built can be pushed with the dockerPush
task.
To both build and push an image use the dockerBuildAndPush
task.
The imageName in docker
key is used to determine which image to push.
Set imageName in docker
of type sbtdocker.ImageName
.
Example:
import DockerKeys._
import sbtdocker.ImageName
imageName in docker := {
ImageName(
namespace = Some(organization.value),
repository = name.value,
tag = Some("v" + version.value))
}
Use the key buildOptions in docker
to set build options.
The expected type is sbtdocker.BuildOptions
which have flags to disable caching and removal of intermediate
containers.
Example:
import DockerKeys._
import sbtdocker.BuildOptions
buildOptions in docker := BuildOptions(noCache = Some(true))
Instead of dockerSettings
the method dockerSettingsAutoPackage(fromImage, exposePorts)
can be used.
This method defines a Dockerfile automatically and uses the package
task to try to generate an artifact.
It's intended purpose is to give a very simple way of creating Docker images for new small projects.
See example projects.