如何使用sbt docker插件复制资源文件

时间:2016-11-09 16:09:45

标签: scala docker sbt

我正在运行使用docker崩溃的应用程序,因为我的应用程序无法访问位于文件夹src/main/resources中的文件。这是我的档案project/plugins.sbt

addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.1.4")

我的build.sbt文件:

organization      := """foo"""

name              := """bar"""

version           := "1.0"

scalaVersion := "2.11.7"

libraryDependencies ++= Seq(
  "org.apache.kafka" % "kafka_2.10" % "0.10.0.0",
  "org.scalatest" % "scalatest_2.11" % "3.0.0-M16-SNAP1",
  "org.scalaz" %% "scalaz-core" % "7.2.5",
  "com.typesafe.akka" %% "akka-actor" % "2.4.11",
  "com.typesafe.play" % "play-json_2.11" % "2.4.8",
  "com.typesafe.scala-logging" %% "scala-logging" % "3.1.0",
  "com.typesafe" % "config" % "1.3.0",
  "com.amazonaws" % "aws-java-sdk" % "1.11.8",
  "ch.qos.logback" % "logback-classic" % "1.1.7",
  "com.typesafe.akka" % "akka-testkit_2.11" % "2.4.12"
)

// the default value in sbt is set to true 
parallelExecution in Test := false 

resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/conigtent/repositories/snapshots"

dependencyOverrides ++= Set(
  "com.fasterxml.jackson.core" % "jackson-databind" % "2.4.4"
)

resolvers ++= Seq(
  "Sonatype Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/",
  "Sonatype Releases" at "https://oss.sonatype.org/content/repositories/releases/"
)

// http://www.scala-sbt.org/sbt-native-packager/formats/docker.html
enablePlugins(DockerPlugin, JavaAppPackaging)
// enablePlugins(JavaAppPackaging)
packageName in Docker := "foo/bar"

这里是主文件:

object FGS_MainApp extends LazyLogging {


  val actorSystemName = "SYS"
  println("Create actor sys " + actorSystemName)
  val system = ActorSystem(actorSystemName)

  private val t = new Thread { 
    override def run() = {
      if (system != null) {
        Database.closeConnection
        system.terminate
        logger.info("ACTOR SYSTEM SHUTDOWN")
      }
    }        
  }

  Runtime.getRuntime.addShutdownHook(t)

  def main(args : Array[String]) = {
    // TODO : this needs to be remove quickly
    val saslPath = getClass.getResource("/sasl.conf").getPath
    println("saslPath = " + saslPath)
    System.setProperty("java.security.auth.login.config", saslPath)
  }
}

然后当我运行命令sbt docker:publishLocal && docker run -it foo/bar:1.0时,我收到了这个错误:

Caused by: java.lang.SecurityException: java.io.IOException: Configuration Error:
    No such file or directory

印刷路径是:

file:/opt/docker/lib/foo.bar-1.0.jar!/sasl.conf

build.sbt中的配置错过了什么?

更新

Caused by: org.apache.kafka.common.KafkaException: java.lang.SecurityException: java.io.IOException: Configuration Error:
    No such file or directory
    at org.apache.kafka.common.network.SaslChannelBuilder.configure(SaslChannelBuilder.java:86)
    at org.apache.kafka.common.network.ChannelBuilders.create(ChannelBuilders.java:70)
    at org.apache.kafka.clients.ClientUtils.createChannelBuilder(ClientUtils.java:83)
    at org.apache.kafka.clients.consumer.KafkaConsumer.<init>(KafkaConsumer.java:623)
    ... 18 more
Caused by: java.lang.SecurityException: java.io.IOException: Configuration Error:
    No such file or directory
    at sun.security.provider.ConfigFile$Spi.<init>(ConfigFile.java:137)
    at sun.security.provider.ConfigFile.<init>(ConfigFile.java:102)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at javax.security.auth.login.Configuration$2.run(Configuration.java:255)
    at javax.security.auth.login.Configuration$2.run(Configuration.java:247)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.login.Configuration.getConfiguration(Configuration.java:246)
    at org.apache.kafka.common.security.authenticator.AbstractLogin.login(AbstractLogin.java:61)
    at org.apache.kafka.common.security.authenticator.LoginManager.<init>(LoginManager.java:46)
    at org.apache.kafka.common.security.authenticator.LoginManager.acquireLoginManager(LoginManager.java:68)
    at org.apache.kafka.common.network.SaslChannelBuilder.configure(SaslChannelBuilder.java:78)
    ... 21 more
Caused by: java.io.IOException: Configuration Error:
    No such file or directory
    at sun.security.provider.ConfigFile$Spi.init(ConfigFile.java:335)
    at sun.security.provider.ConfigFile$Spi.init(ConfigFile.java:271)
    at sun.security.provider.ConfigFile$Spi.<init>(ConfigFile.java:135)
    ... 35 more

它显示了这一行:

private val kafkaConsumer = new KafkaConsumer[String, Array[Byte]](kafkaProps)其中kafkaProps的类型为java.util.Properties。所以它无法在资源文件夹中找到该文件。

1 个答案:

答案 0 :(得分:1)

您遇到的问题是如何处理src/main/resources。这是一个特殊的文件夹,其内容将包含在由sbt构建的jar文件中。它实际上从未作为文件复制到您的通用包中。这就是为什么打印出来的文件路径包含jar名称和! - 这意味着文件是里面压缩的jar。很明显,kafka库没有处理这个问题。

要解决此问题,您应该将文件放在不同的位置,例如src/main/conf(可选,但严格来说更正确),然后将其映射到您的通用包中:

mappings.in(Universal) +=
  ((sourceDirectory.value / "main" / "conf" / "sasl.conf"), "conf/sasl.conf"))

现在,您可以在通用套餐中将其作为文件conf/sasl.conf使用。