我正在使用 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")
)
)
问题:
上面的代码不起作用,因为即使我已经验证 fullPathToMod1Art 对于生成的 mod1 工件是正确的,根模块也找不到 mod1 工件。我通过compile->test指定了rootdependsOn mod1,因为我不知道还有什么其他配置更能描述需求:root的docker镜像创建依赖于mod1 fat jar的生成。
如您所见,在根模块设置中获取 mod1 工件路径存在令人讨厌的路径解析。一定有更好的办法。
问题:
如果 sbt-docker + sbt-assembly 解决方案支持 AFIO 模型,如何正确地做到这一点,从而优雅地解决上述两个问题?如果他们不支持,还有哪些插件可以提供帮助?
感谢任何线索。