Skip to content

Commit

Permalink
Adding 'dockerBuild{Command, Options}' and renaming 'dockerTag' (#854)
Browse files Browse the repository at this point in the history
* dockerBuildCommand
The 'dockerBuildCommand' let users customize the command for building
Docker images.
The current default is 'docker build [dockerBuildOptions] .'.

* dockerBuildOptions
Furthermore 'dockerBuildOptions' defines which build options are used.
The current default is '--force-rm -t [dockerAlias]' (which is expanded
if 'dockerUpdateLatest' is set to 'true'.

This results in an execution of 'docker build --force-rm -t
[dockerAlias] .' (if 'dockerUpdateLatest' is 'false').

* dockerTag being renamed to dockerAlias
The 'dockerTag' setting is renamed to 'dockerAlias' as this better
reflects the setting. Docker aliases consist of a registry path,
username, name and tag ([REGISTRY_HOST/][USERNAME/]NAME[:TAG]).
To not confuse the Docker image tag with this setting (as it takes the
full alias name), the setting is renamed.
  • Loading branch information
makubi authored and muuki88 committed Aug 4, 2016
1 parent 0aeb692 commit a125a60
Show file tree
Hide file tree
Showing 19 changed files with 97 additions and 40 deletions.
19 changes: 19 additions & 0 deletions src/main/scala/com/typesafe/sbt/packager/docker/DockerAlias.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.typesafe.sbt.packager.docker

/**
* This class represents a Docker alias.
* It generates a string in the form of {{{[REGISTRY_HOST/][USERNAME/]NAME[:TAG]}}},
* e.g. ''my-registry.com:1234/my-user/my-service:1.0.0'' or just ''my-service:1.0.0''.
* @param registryHost Optional hostname of the registry (including port if applicable)
* @param username Optional username or other qualifier
* @param name Name of the image, e.g. the artifact name
* @param tag Optional tag for the image, e.g. the version
*/
case class DockerAlias(registryHost: Option[String], username: Option[String], name: String, tag: Option[String]) {
protected val untagged = registryHost.map(_ + "/").getOrElse("") + username.map(_ + "/").getOrElse("") + name

/** Tag with (optional) given version */
val versioned = untagged + tag.map(":" + _).getOrElse("")
/** Tag with version 'latest' */
val latest = s"$untagged:latest"
}
46 changes: 21 additions & 25 deletions src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ object DockerPlugin extends AutoPlugin {

object autoImport extends DockerKeys {
val Docker = config("docker")

val DockerAlias = com.typesafe.sbt.packager.docker.DockerAlias
}

import autoImport._
Expand All @@ -74,10 +76,17 @@ object DockerPlugin extends AutoPlugin {
dockerExposedPorts := Seq(),
dockerExposedVolumes := Seq(),
dockerRepository := None,
dockerTag := dockerRepository.value.map(_ + "/").getOrElse("") + packageName.value + ":" + version.value,
dockerAlias := DockerAlias(dockerRepository.value, None, packageName.value, Some(version.value)),
dockerUpdateLatest := false,
dockerEntrypoint := Seq("bin/%s" format executableScriptName.value),
dockerCmd := Seq(),
dockerBuildOptions := Seq("--force-rm") ++ Seq("-t", dockerAlias.value.versioned) ++ (
if (dockerUpdateLatest.value)
Seq("-t", dockerAlias.value.latest)
else
Seq()
),
dockerBuildCommand := Seq("docker", "build") ++ dockerBuildOptions.value ++ Seq("."),
dockerCommands := {
val dockerBaseDirectory = (defaultLinuxInstallLocation in Docker).value
val user = (daemonUser in Docker).value
Expand Down Expand Up @@ -106,16 +115,16 @@ object DockerPlugin extends AutoPlugin {
mappings ++= Seq(dockerGenerateConfig.value) pair relativeTo(target.value),
name := name.value,
packageName := packageName.value,
publishLocal <<= (stage, dockerTag, dockerUpdateLatest, streams) map {
(context, target, updateLatest, s) =>
publishLocalDocker(context, target, updateLatest, s.log)
publishLocal <<= (stage, dockerAlias, dockerBuildCommand, streams) map {
(context, alias, buildCommand, s) =>
publishLocalDocker(context, buildCommand, s.log)
s.log.info(s"Built image $alias")
},
publish <<= (publishLocal, dockerTag, dockerUpdateLatest, streams) map {
(_, target, updateLatest, s) =>
publishDocker(target, s.log)
publish <<= (publishLocal, dockerAlias, dockerUpdateLatest, streams) map {
(_, alias, updateLatest, s) =>
publishDocker(alias.versioned, s.log)
if (updateLatest) {
val name = target.substring(0, target.lastIndexOf(":")) + ":latest"
publishDocker(name, s.log)
publishDocker(alias.latest, s.log)
}
},
sourceDirectory := sourceDirectory.value / "docker",
Expand Down Expand Up @@ -283,27 +292,14 @@ object DockerPlugin extends AutoPlugin {
}
}

def publishLocalDocker(context: File, tag: String, latest: Boolean, log: Logger): Unit = {
val cmd = Seq("docker", "build", "--force-rm", "-t", tag, ".")

log.debug("Executing Native " + cmd.mkString(" "))
def publishLocalDocker(context: File, buildCommand: Seq[String], log: Logger): Unit = {
log.debug("Executing Native " + buildCommand.mkString(" "))
log.debug("Working directory " + context.toString)

val ret = Process(cmd, context) ! publishLocalLogger(log)
val ret = Process(buildCommand, context) ! publishLocalLogger(log)

if (ret != 0)
throw new RuntimeException("Nonzero exit value: " + ret)
else
log.info("Built image " + tag)

if (latest) {
val name = tag.substring(0, tag.lastIndexOf(":")) + ":latest"
val latestCmd = Seq("docker", "tag", tag, name)
Process(latestCmd).! match {
case 0 => log.info("Update Latest from image " + tag)
case n => sys.error("Failed to run docker tag")
}
}
}

def publishDocker(tag: String, log: Logger): Unit = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ object DockerSpotifyClientPlugin extends AutoPlugin {

def publishLocalDocker = Def.task {
val context = stage.value
val tag = dockerTag.value
val tag = dockerAlias.value.versioned
val latest = dockerUpdateLatest.value
val log = streams.value.log

Expand Down
4 changes: 3 additions & 1 deletion src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ trait DockerKeys {
val dockerExposedPorts = SettingKey[Seq[Int]]("dockerExposedPorts", "Ports exposed by Docker image")
val dockerExposedVolumes = SettingKey[Seq[String]]("dockerExposedVolumes", "Volumes exposed by Docker image")
val dockerRepository = SettingKey[Option[String]]("dockerRepository", "Repository for published Docker image")
val dockerTag = SettingKey[String]("dockerTag", "Docker tag for the built image")
val dockerAlias = SettingKey[DockerAlias]("dockerAlias", "Docker alias for the built image")
val dockerUpdateLatest = SettingKey[Boolean]("dockerUpdateLatest", "Set to update latest tag")
val dockerEntrypoint = SettingKey[Seq[String]]("dockerEntrypoint", "Entrypoint arguments passed in exec form")
val dockerCmd = SettingKey[Seq[String]]("dockerCmd", "Docker CMD. Used together with dockerEntrypoint. Arguments passed in exec form")
val dockerBuildOptions = SettingKey[Seq[String]]("dockerBuildOptions", "Options used for the Docker build")
val dockerBuildCommand = SettingKey[Seq[String]]("dockerBuildCommand", "Command for building the Docker image")

val dockerCommands = TaskKey[Seq[CmdLike]]("dockerCommands", "List of docker commands that form the Dockerfile")
}
Expand Down
7 changes: 7 additions & 0 deletions src/sbt-test/docker/alias/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
enablePlugins(JavaAppPackaging)

name := "docker-alias-test"

version := "0.1.0"

dockerAlias := DockerAlias(None, None, "docker-alias-test", Some("0.1.0"))
File renamed without changes.
3 changes: 3 additions & 0 deletions src/sbt-test/docker/alias/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Stage the distribution and ensure files show up.
> docker:publishLocal
$ exec bash -c 'docker run docker-alias-test:0.1.0 | grep -q "Hello world"'
9 changes: 9 additions & 0 deletions src/sbt-test/docker/build-command/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
enablePlugins(JavaAppPackaging)

name := "docker-build-command-test"

version := "0.1.0"

import NativePackagerHelper._
mappings in Docker ++= directory("src/main/resources/docker-test")
dockerBuildCommand := Seq("docker", "build", "-t", "docker-build-command-test:0.1.0", "docker-test/")
1 change: 1 addition & 0 deletions src/sbt-test/docker/build-command/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % sys.props("project.version"))
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM busybox

CMD ["echo", "docker build command override test"]
3 changes: 3 additions & 0 deletions src/sbt-test/docker/build-command/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Stage the distribution and ensure files show up.
> docker:publishLocal
$ exec bash -c 'docker run docker-build-command-test:0.1.0 | grep -q "docker build command override test"'
7 changes: 7 additions & 0 deletions src/sbt-test/docker/build-options/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
enablePlugins(JavaAppPackaging)

name := "docker-build-options-test"

version := "0.1.0"

dockerBuildOptions := dockerBuildOptions.value ++ Seq("-t", "docker-build-options-test:0.1.0-random-tag")
1 change: 1 addition & 0 deletions src/sbt-test/docker/build-options/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % sys.props("project.version"))
3 changes: 3 additions & 0 deletions src/sbt-test/docker/build-options/src/main/scala/Main.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object Main extends App {
println("Hello world")
}
4 changes: 4 additions & 0 deletions src/sbt-test/docker/build-options/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Stage the distribution and ensure files show up.
> docker:publishLocal
$ exec bash -c 'docker run docker-build-options-test:0.1.0 | grep -q "Hello world"'
$ exec bash -c 'docker run docker-build-options-test:0.1.0-random-tag | grep -q "Hello world"'
7 changes: 0 additions & 7 deletions src/sbt-test/docker/tag/build.sbt

This file was deleted.

3 changes: 0 additions & 3 deletions src/sbt-test/docker/tag/test

This file was deleted.

15 changes: 12 additions & 3 deletions src/sphinx/formats/docker.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,18 @@ Publishing Settings
``dockerUpdateLatest``
The flag to automatic update the latest tag when the ``docker:publish`` task is run. Default value is ``FALSE``.

``dockerTag``
The tag to be used during build for the resulting image.
Defaults to ``[dockerRepository]/[name]:[version]``.
``dockerAlias``
The alias to be used for tagging the resulting image of the Docker build.
The type of the setting key is ``DockerAlias`.
Defaults to ``[dockerRepository/][name]:[version]``.

``dockerBuildOptions``
Overrides the default Docker build options.
Defaults to ``Seq("--force-rm", "-t", "[dockerAlias]")``. This default is expanded if ``dockerUpdateLatest`` is set to true.

``dockerBuildCommand``
Overrides the default Docker build command.
Defaults to ``Seq("docker", "build", "[dockerBuildOptions]", ".")``.

Tasks
-----
Expand Down

0 comments on commit a125a60

Please sign in to comment.