在 Play JPA 项目中使用 sbt-native-packager 将自定义文件夹添加到 Docker

Posted

技术标签:

【中文标题】在 Play JPA 项目中使用 sbt-native-packager 将自定义文件夹添加到 Docker【英文标题】:Adding custom folder to Docker using sbt-native-packager in Play JPA project 【发布时间】:2017-04-12 11:30:39 【问题描述】:

我正在开发一个 JPA + Playframework 2.5.x 项目,我将其打包为 Docker 映像。

我想将conf文件夹下除了一个文件(META-INF/persistence.xml)以外的所有文件强制添加到docker输出

目前我做了以下工作:

mappings in Docker += file("conf/base/application.conf") -> "opt/docker/conf/base/application.conf"
mappings in Docker += file("conf/base/default-client.conf") -> "opt/docker/conf/base/default-client.conf"
mappings in Docker += file("conf/prod/application.conf") -> "opt/docker/conf/prod/application.conf"
mappings in Docker += file("conf/prod/logback.xml") -> "opt/docker/conf/prod/logback.xml"
mappings in Docker += file("conf/stage/application.conf") -> "opt/docker/conf/stage/application.conf"
mappings in Docker += file("conf/stage/logback.xml") -> "opt/docker/conf/stage/logback.xml"
mappings in Docker += file("conf/local/application.conf") -> "opt/docker/conf/local/application.conf"
mappings in Docker += file("conf/local/logback.xml") -> "opt/docker/conf/local/logback.xml"
mappings in Docker += file("conf/routes") -> "opt/docker/conf/routes"
mappings in Docker += file("conf/ValidationMessages.properties") -> "opt/docker/conf/ValidationMessages.properties"

我确信这不是实现这一目标的最佳方式。任何人都可以建议更好的选择来按照我需要的方式自定义 Docker 输出吗?

我的 build.sbt 文件:

PlayKeys.externalizeResources := false
name := """wp-pw-ng"""

version := "1.0.0-SNAPSHOT"

lazy val `wp-pw-ng` = (project in file(".")).enablePlugins(PlayJava, JavaAppPackaging)

val playVer = "2.5.9"

scalaVersion := "2.11.8"

libraryDependencies ++= Seq(
  javaJpa,
  "org.hibernate" % "hibernate-core" % "5.2.3.Final" exclude("dom4j", "dom4j"),
  "mysql" % "mysql-connector-java" % "6.0.5",
  cache,
  javaWs,
  filters,
  "dom4j" % "dom4j" % "1.6",
  "com.google.guava" % "guava" % "20.0-rc1",
  "com.amazonaws" % "aws-java-sdk" % "1.11.34"
)

val docDeps = Seq(
  "io.swagger" %% "swagger-play2" % "1.5.3.2"
)

libraryDependencies ++= docDeps

fork in Test := true
javaOptions in Test ++= Seq(
  "-Xms512M",
  "-Xmx1536M",
  "-Xss1M",
  "-XX:MaxPermSize=384M"
)

fork in run := false

unmanagedResourceDirectories in Compile <+= (sourceDirectory in Compile) (_ / "resources")

mappings in Docker += file("conf/base/application.conf") -> "opt/docker/conf/base/application.conf"
mappings in Docker += file("conf/base/default-client.conf") -> "opt/docker/conf/base/default-client.conf"
mappings in Docker += file("conf/base/pw.conf") -> "opt/docker/conf/base/paywall.conf"
mappings in Docker += file("conf/prod/application.conf") -> "opt/docker/conf/prod/application.conf"
mappings in Docker += file("conf/prod/logback.xml") -> "opt/docker/conf/prod/logback.xml"
mappings in Docker += file("conf/stage/application.conf") -> "opt/docker/conf/stage/application.conf"
mappings in Docker += file("conf/stage/logback.xml") -> "opt/docker/conf/stage/logback.xml"
mappings in Docker += file("conf/local/application.conf") -> "opt/docker/conf/local/application.conf"
mappings in Docker += file("conf/local/logback.xml") -> "opt/docker/conf/local/logback.xml"
mappings in Docker += file("conf/routes") -> "opt/docker/conf/routes"
mappings in Docker += file("conf/ValidationMessages.properties") -> "opt/docker/conf/ValidationMessages.properties"

//************************************************
// Custom Docker Build,
// use command 'activator docker:publishLocal'
// to publish image locally to computer.
//************************************************
import com.typesafe.sbt.packager.docker._

val playUser = "play"
val grp = "idud"
dockerRepository := Some("quay.io/we")

version in Docker := "latest"

val buildEnv: String = System.getProperty("build.env")

dockerCommands := Seq(
  Cmd("FROM", "anapsix/alpine-java:8_jdk_unlimited"),
  Cmd("RUN", "apk", "-Uuv add", "--no-cache", "su-exec", "groff", "less", "python", "py-pip", "&& pip install awscli ", "&&  apk --purge -v del py-pip ", " &&  rm /var/cache/apk/* "),
  Cmd("RUN", s"addgroup $grp"),
  Cmd("RUN", s"adduser -s /bin/bash -D -G $grp $playUser"),
  Cmd("RUN", "echo", s"'$playUser ALL=(ALL) NOPASSWD:ALL'", ">> /etc/sudoers"),
  Cmd("WORKDIR", "/opt/docker"),
  Cmd("ADD", "opt /opt"),
  Cmd("RUN", "chown", "-R", s"$playUser:$grp", "."),
  Cmd("USER", s"$playUser"),
  Cmd("ENTRYPOINT", "[\"bin/wp-pw-ng\", \"-Dconfig.file=conf/" + buildEnv + "/application.conf\", \"-Dhttp.port=7000\" , \"-Dpidfile.path=/dev/null\"  ,\"-Dlogger.file=conf/" + buildEnv + "/logback.xml\"]"),
  Cmd("EXPOSE", "9877")
)

其他信息 由于 Playframework、Issue 4590 的构建 stage 模式问题,我不得不求助于这个解决方法,并且我不得不在我的 build.sbt 文件中使用 PlayKeys.externalizeResources := false 标志。这将删除 Docker 中 conf 文件夹中的所有文件。

【问题讨论】:

【参考方案1】:

playExternalizeResources:= false 将 just prevents sbtfrom adding 设置为 playExternalizedResources 到您的 mappings in Universal,这些映射适用于包括 docker 在内的所有目标包格式。

您的构建 sbt 可以使用 MappingsHelper ( ScalaDocs ) 来减轻

import NativePackagerHelper._
mappings in Universal ++= contentOf("conf")

您还可以过滤映射以删除不需要的文件,例如

import NativePackagerHelper._
mappings in Universal ++= contentOf("conf").filter(_.2.contains("persistence.xml")

希望对您有所帮助, 渚

【讨论】:

这不起作用,因为在 docker stage 文件夹中,我需要将文件放在opt/docker/conf/ 下,只需将它们添加为mappings in Docker ++= contentOf("conf") 将其添加到target/stage 文件夹下。我需要将文件重新映射到opt/docker/conf/ 然后使用directory 而不是contentOf 并映射生成的映射。就像您对任何其他 Scala 集合所做的那样【参考方案2】:

只需将要映射的文件添加到universal/conf 目录中即可。因此,当您创建 docker 映像时,文件会添加到 /opt/docker/conf 目录中。

【讨论】:

以上是关于在 Play JPA 项目中使用 sbt-native-packager 将自定义文件夹添加到 Docker的主要内容,如果未能解决你的问题,请参考以下文章

JPA 和 Play 框架:EntityManager 没有名为更新的持久性提供程序

Play 2.4 / Ebean / JPA / hibernate-entitymanager 的正确配置是啥?

JPA和Threads在play框架中

在 jpa play 框架中按字段查找

使用“in”在 Play Framework 1.x / JPA 中构建查询的更简单方法?

使用 play framework 1.+ 指定图像名称(使用 play.db.jpa.blob)