2

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

假设这个多模块项目有模块根和 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. 上面的代码不起作用,因为即使我已经验证 fullPathToMod1Art 对于生成的 mod1 工件是正确的,根模块也找不到 mod1 工件。我通过compile->test指定了rootdependsOn mod1,因为我不知道还有什么其他配置更能描述需求:root的docker镜像创建依赖于mod1 fat jar的生成。

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

问题:

如果 sbt-docker + sbt-assembly 解决方案支持 AFIO 模型,如何正确地做到这一点,从而优雅地解决上述两个问题?如果他们不支持,还有哪些插件可以提供帮助?

感谢任何线索。

4

1 回答 1

3

由于您想使用子项目中的程序集输出,您应该使docker根项目中的任务依赖于assembly子项目中的任务:

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

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

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

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

希望这能解决您的问题。

于 2015-05-25T11:36:15.003 回答