如何使用sbt-docker和sbt-assembly创建一体化docker镜像

时间:2015-05-21 14:55:33

标签: docker sbt-assembly sbt-docker

我正在使用sbt-assembly来获取胖罐并使用sbt-docker来创建和推送docker镜像。我的项目是多模块,有多个Web服务,UI,数据库等。由于我的基础docker镜像很大(800M),我想创建一个包含所有胖罐的docker镜像,这样我就可以轻松地在云端测试一台普通的机器。我把这个解决方案称为All-FatJars-in-One(AFIO)。我很难在这篇文章中构建这样的AFIO docker图像。

假设这个多模块项目有模块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工件,即使我已经验证了fullPathToMod1Art对于生成的mod1工件是正确的。我通过compile-&gt;测试指定了根dependsOn mod1,因为我不知道其他配置更适合描述需要:root的docker图像创建依赖于mod1 fat jar生成。

  2. 如您所见,在根模块设置中有令人讨厌的路径解析来获取mod1工件路径。必须有更好的方法。

  3. 问题:

    如果sbt-docker + sbt-assembly解决方案支持AFIO模型,那么如何才能正确地完成这两个问题才能优雅地解决?如果他们不支持,其他插件可以提供哪些帮助?

    感谢任何线索。

1 个答案:

答案 0 :(得分:2)

由于您要使用子项目的汇编输出,因此您应该在根项目中使docker任务取决于子项目中的assembly任务:

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

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

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

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

希望这能解决你的问题。