diff --git a/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala b/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala index 77849c7f1..bd02df54c 100644 --- a/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala +++ b/src/main/scala/com/typesafe/sbt/packager/docker/DockerPlugin.scala @@ -65,6 +65,8 @@ object DockerPlugin extends AutoPlugin { dockerExposedVolumes := Seq(), dockerRepository := None, dockerUpdateLatest := false, + dockerRawWithOriginalUser := "", + dockerRawWithDaemonUser := "", dockerEntrypoint := Seq("bin/%s" format executableScriptName.value) ) ++ mapGenericFilesToDocker ++ inConfig(Docker)(Seq( @@ -97,7 +99,7 @@ object DockerPlugin extends AutoPlugin { MappingsHelper contentOf dir }, dockerGenerateConfig <<= (dockerBaseImage, defaultLinuxInstallLocation, - maintainer, daemonUser, executableScriptName, + maintainer, dockerRawWithOriginalUser, daemonUser, dockerRawWithDaemonUser, executableScriptName, dockerExposedPorts, dockerExposedVolumes, target, dockerEntrypoint) map generateDockerConfig, dockerTarget <<= (dockerRepository, packageName, version) map { (repo, name, version) => @@ -105,7 +107,7 @@ object DockerPlugin extends AutoPlugin { } )) - private[this] final def makeDockerContent(dockerBaseImage: String, dockerBaseDirectory: String, maintainer: String, daemonUser: String, execScript: String, exposedPorts: Seq[Int], exposedVolumes: Seq[String], entrypoint: Seq[String]) = { + private[this] final def makeDockerContent(dockerBaseImage: String, dockerBaseDirectory: String, maintainer: String, dockerRawWithOriginalUser:String, daemonUser: String, dockerRawWithDaemonUser:String, execScript: String, exposedPorts: Seq[Int], exposedVolumes: Seq[String], entrypoint: Seq[String]) = { val fromCommand = Cmd("FROM", dockerBaseImage) val maintainerCommand: Option[Cmd] = { @@ -121,7 +123,9 @@ object DockerPlugin extends AutoPlugin { Cmd("ADD", s"$files /$files"), Cmd("WORKDIR", "%s" format dockerBaseDirectory), ExecCmd("RUN", "chown", "-R", daemonUser, "."), + Raw(dockerRawWithOriginalUser), Cmd("USER", daemonUser), + Raw(dockerRawWithDaemonUser), ExecCmd("ENTRYPOINT", entrypoint: _*), ExecCmd("CMD") ) @@ -155,9 +159,9 @@ object DockerPlugin extends AutoPlugin { } private[this] final def generateDockerConfig( - dockerBaseImage: String, dockerBaseDirectory: String, maintainer: String, daemonUser: String, execScript: String, exposedPorts: Seq[Int], exposedVolumes: Seq[String], target: File, entrypoint: Seq[String] + dockerBaseImage: String, dockerBaseDirectory: String, maintainer: String, dockerRawWithOriginalUser:String, daemonUser: String, dockerRawWithDaemonUser:String, execScript: String, exposedPorts: Seq[Int], exposedVolumes: Seq[String], target: File, entrypoint: Seq[String] ) = { - val dockerContent = makeDockerContent(dockerBaseImage, dockerBaseDirectory, maintainer, daemonUser, execScript, exposedPorts, exposedVolumes, entrypoint) + val dockerContent = makeDockerContent(dockerBaseImage, dockerBaseDirectory, maintainer, dockerRawWithOriginalUser, daemonUser, dockerRawWithDaemonUser, execScript, exposedPorts, exposedVolumes, entrypoint) val f = target / "Dockerfile" IO.write(f, dockerContent) diff --git a/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala b/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala index c8042d921..3e32dfded 100644 --- a/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala +++ b/src/main/scala/com/typesafe/sbt/packager/docker/Keys.scala @@ -17,6 +17,8 @@ trait DockerKeys { val dockerExposedVolumes = SettingKey[Seq[String]]("dockerExposedVolumes", "Volumes exposed by Docker image") val dockerRepository = SettingKey[Option[String]]("dockerRepository", "Repository for published Docker image") val dockerUpdateLatest = SettingKey[Boolean]("dockerUpdateLatest", "Set to update latest tag") + val dockerRawWithOriginalUser = SettingKey[String]("dockerRawWithOriginalUser", "Raw docker commands to be executed BEFORE the daemon user is set") + val dockerRawWithDaemonUser = SettingKey[String]("dockerRawWithDaemonUser", "Raw docker commands to be executed AFTER the daemon user is set") val dockerEntrypoint = SettingKey[Seq[String]]("dockerEntrypoint", "Entrypoint arguments passed in exec form") } diff --git a/src/main/scala/com/typesafe/sbt/packager/docker/dockerfile.scala b/src/main/scala/com/typesafe/sbt/packager/docker/dockerfile.scala index 3165141dc..590aec86c 100644 --- a/src/main/scala/com/typesafe/sbt/packager/docker/dockerfile.scala +++ b/src/main/scala/com/typesafe/sbt/packager/docker/dockerfile.scala @@ -51,6 +51,22 @@ case class Cmd(cmd: String, arg: String) extends CmdLike { def makeContent = "%s %s\n" format (cmd, arg) } +/** + * An raw command + * + * @example + * {{{ + * val raw = Cmd(""" + * | RUN [ "grep newguy /etc/passwd && echo user exist || useradd newguy" ] + * | # a comment + * | ADD /a/b /c/d + * """.stripMargin) + * }}} + */ +case class Raw(script: String) extends CmdLike { + def makeContent = script + "\n" +} + /** Represents dockerfile used by docker when constructing packages. */ case class Dockerfile(commands: CmdLike*) { def makeContent: String = { diff --git a/test-project-docker/build.sbt b/test-project-docker/build.sbt index f812fe56d..ecc352e4a 100644 --- a/test-project-docker/build.sbt +++ b/test-project-docker/build.sbt @@ -5,3 +5,14 @@ name := "docker-test" version := "0.1.0" maintainer := "Gary Coady " + +dockerRawWithOriginalUser := """ +RUN [ "grep newguy /etc/passwd && echo user exist || useradd newguy" ] +RUN [ "echo $USER > /tmp/test" ] +""" + +daemonUser := "newguy" + +dockerRawWithDaemonUser := """ +RUN [ "touch", "/tmp/newguy-testfile" ] +""" \ No newline at end of file