如何使用sbt-docker和sbt-assembly创build一个All-in-One泊坞窗图像

我正在使用sbt-assembly来获得脂肪jar,并使用sbt-docker来创build并推送泊坞窗图像。 我的项目是多模块,它有多个Web服务,用户界面,数据库等。由于我的基础docker图像是大的(800M),我想创build一个包含所有胖jar子的docker图像,以便我可以轻松地使用云testing一个适度的机器。 我把这个解决scheme称为All-FatJars-in-One(AFIO)。 我很难build立这样的AFIOdocker图像,因此这篇文章。

假设这个多模块项目有模块root和mod1,下面是build.scala:

val exeProjs = Seq(mod1) lazy val root = Project("root", file(".")). enablePlugins(DockerPlugin). aggregate(exeProjs.map(_.project): _*). dependsOn(exeProjs.map(_ % "compile->test"): _*). settings(basicSettings: _*). settings( docker <<= docker dependsOn assembly, dockerfile in docker := { //get root artifact path like // /home/me/root/target/scala-2.11/root-assembly-0.1-SNAPSHOT.jar val parentArtifact = (assemblyOutputPath in assembly).value new Dockerfile { from("java:8") exeProjs.map(proj => { val projName = proj.id // fullPathToMod1Art will be like // /home/me/root/mod1/target/scala-2.11/mod1-assembly-0.1-SNAPSHOT.jar fullPathToMod1Art = { NASTY parsing to get mo1 artifact } val artifactTargetPath = s"/app/$projName/$artifact" addRaw(fullPathArt, artifactTargetPath) }) } } imageNames in docker := Seq( ImageName("myaccount/root:v1") ) ) lazy val mod1 = Project("mod1", file("mod1")). enablePlugins(DockerPlugin). settings(basicSettings: _*). settings( libraryDependencies ++= Seq(spray_can, spray_routing, akka_actor, junit), docker <<= docker dependsOn assembly, dockerfile in docker := { val artifact = (assemblyOutputPath in assembly).value val artifactTargetPath = s"/app/${artifact.name}" new Dockerfile { from("java:8") add(artifact, artifactTargetPath) entryPoint("java", "-jar", artifactTargetPath) } }, imageNames in docker := Seq( ImageName("myaccount/mod1:v1") ) ) 

问题:

  1. 上面的代码不起作用,因为根模块找不到mod1神器,即使我已经validation了fullPathToMod1Art对于生成的mod1神器是正确的。 我通过compile-> test指定了根dependsOn mod1,因为我不知道其他configuration是否更好地描述需求:root的docker映像创build取决于mod1的fat jar生成。

  2. 正如你所看到的,在根模块设置中有一个讨厌的pathparsing来获取mod1工件path。 一定有更好的办法。

问题:

如果sbt-docker + sbt-assembly解决scheme支持AFIO模型,那么如何正确地做到这一点,以上两个问题就被优雅地解决了? 如果他们不支持,还有哪些插件可以帮助?

欣赏任何线索。

既然你想使用你的子项目中的程序集输出,你应该在你的子项目中使docker任务依赖于你的子项目中的assembly任务:

 docker <<= docker.dependsOn(assembly in mod1, assembly in mod2) 

目前你有docker <<= docker dependsOn assembly ,它将为根项目生成一个胖JAR。

您也可以像这样为您的子项目获取程序集输出path:

 val jarFile = (outputPath in assembly in mod1).value 

希望这可以解决你的问题。

Interesting Posts