【问题标题】:Why is sbt-native-packager staging bin/start as a directory instead of a script?为什么 sbt-native-packager 将 bin/start 暂存为目录而不是脚本?
【发布时间】:2014-09-29 02:31:21
【问题描述】:

我正在使用 sbt-native-packager 和 sbt-docker 来生成 Docker 映像,如 this tutorial 中所述。 Docker 镜像不会运行(权限被拒绝),检查后发现bin/start 被创建为一个空目录。

dan@cobalt:~/projects/confabulous/deva$ ls -l target/universal/stage/bin/
total 24
-rwxrw-r-- 1 dan dan 11591 Aug  5 20:44 deva
-rw-rw-r-- 1 dan dan  6211 Aug  5 20:44 deva.bat
drwxrwxr-x 2 dan dan  4096 Dec 31  1969 start

由于某种原因,它也有一个空时间戳。为什么它被创建为目录而不是 shell 脚本?

这是我的 plugins.sbt:

addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.4")

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

addSbtPlugin("io.spray" % "sbt-revolver" % "0.7.1")

addSbtPlugin("se.marcuslonnberg" % "sbt-docker" % "0.5.0")

resolvers += Classpaths.sbtPluginReleases

这是我的 build.sbt:

import DockerKeys._
import sbtdocker.{Dockerfile, ImageName}
import com.typesafe.sbt.packager.Keys._

organization  := "com.confabulous"

name          := "deva"

version       := "0.0.1"

scalaVersion  := "2.10.3"

scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8", "-language:postfixOps")

resolvers ++= Seq(
  "sonatype releases"  at "https://oss.sonatype.org/content/repositories/releases/",
  "sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/",
  "typesafe repo"      at "http://repo.typesafe.com/typesafe/releases/"
)

libraryDependencies ++= Seq(
  "ch.qos.logback"      %   "logback-classic" % "1.0.9",
  "com.typesafe.akka"   %   "akka-slf4j_2.10" % "2.3.3",
  "com.typesafe.akka"   %%  "akka-actor"      % "2.3.3",
  "com.typesafe.akka"   %%  "akka-remote"     % "2.3.3",
  "com.typesafe.akka"   %%  "akka-agent"      % "2.3.3",
  "com.typesafe.slick"  %%  "slick"           % "2.0.1-RC1",
  "org.mozilla"         %   "rhino"           % "1.7R4",
  "org.postgresql"      %   "postgresql"      % "9.3-1101-jdbc3",
  "org.msgpack"         %%  "msgpack-scala"   % "0.6.8",
  "com.livestream"      %%  "scredis"         % "1.1.2",
  "com.confabulous"     %%  "messages"        % "0.0.1-SNAPSHOT",
  "com.confabulous"     %%  "db"              % "0.0.1-SNAPSHOT"
)

packageArchetype.java_server

sbtdocker.Plugin.dockerSettings

mappings in Universal += baseDirectory.value / "docker" / "start" -> "bin/start"

docker <<= docker.dependsOn(com.typesafe.sbt.packager.universal.Keys.stage.in(Compile))

// Define a Dockerfile
dockerfile in docker <<= (name, stagingDirectory in Universal) map {
    case (appName, stageDir) =>
        val workingDir = s"/opt/${appName}"
        new Dockerfile {
            // Use a base image that contain Java
            from("relateiq/oracle-java7")
            maintainer("Dan Ellis <dan@halftreelabs.com>")
            expose(1600)
            add(stageDir, workingDir)
            run("chmod",  "+x",  s"/opt/${appName}/bin/${appName}")
            run("chmod",  "+x",  s"/opt/${appName}/bin/start")
            workDir(workingDir)
            entryPointShell(s"bin/start", appName, "$@")
        }
}

imageName in docker := {
    ImageName(
        namespace = Some("confabulous.com"),
        repository = name.value
        //,tag = Some("v" + version.value))
    )
}

【问题讨论】:

    标签: scala sbt docker sbt-native-packager


    【解决方案1】:

    引用的文章是系列文章的第 2 部分,其中容器的地址通过脚本传递到 Java 程序中。脚本本身在part 1 中引用。

    mappings in Universal 采用一系列 (File, String) 元组。文件被复制到结果图像中字符串指定的路径。

    在这种情况下,如果baseDirectory.value / "docker" / "start" 处没有文件,则无法复制任何内容,结果就是您描述的行为。

    您应该创建一个适当的启动脚本,如第 1 部分所述。

    【讨论】:

    • 啊,对了,我错过了那个小小的单行脚本。我以为它是一个更大的脚本 sbt-native-packager 生成的,但它只是创建了另一个(在这种情况下为bin/deva)。
    【解决方案2】:

    另一种选择是利用 sbt-native-packager 中对 Docker 的实验性支持。

    如果您从 build.sbt 中删除与 Docker 相关的行,并添加 maintainer 设置,您可以:

    sbt docker:stagetarget/docker/stage 中生成 Dockerfile 和上下文

    sbt docker:publishLocal生成本地图片

    sbt docker:publish生成图片并远程推送

    如果要修改传递给启动脚本的命令,可以进行如下修改:

    bashScriptExtraDefines := Seq(
      "CLUSTER_IP=$(/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}')",
      "addResidual ${CLUSTER_IP}"
    )
    

    addResidual 是 sbt-native-packager 生成的启动脚本中的一个函数,它为程序的命令行参数添加了一个额外的参数。

    addJava 是一个向运行您的程序的 Java 二进制文件添加额外参数的函数。


    您的build.sbt 可能如下所示:

    import com.typesafe.sbt.packager.Keys._
    
    organization  := "com.confabulous"
    
    name          := "deva"
    
    version       := "0.0.1"
    
    scalaVersion  := "2.10.3"
    
    scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8", "-language:postfixOps")
    
    resolvers ++= Seq(
      "sonatype releases"  at "https://oss.sonatype.org/content/repositories/releases/",
      "sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/",
      "typesafe repo"      at "http://repo.typesafe.com/typesafe/releases/"
    )
    
    libraryDependencies ++= Seq(
      "ch.qos.logback"      %   "logback-classic" % "1.0.9",
      "com.typesafe.akka"   %   "akka-slf4j_2.10" % "2.3.3",
      "com.typesafe.akka"   %%  "akka-actor"      % "2.3.3",
      "com.typesafe.akka"   %%  "akka-remote"     % "2.3.3",
      "com.typesafe.akka"   %%  "akka-agent"      % "2.3.3",
      "com.typesafe.slick"  %%  "slick"           % "2.0.1-RC1",
      "org.mozilla"         %   "rhino"           % "1.7R4",
      "org.postgresql"      %   "postgresql"      % "9.3-1101-jdbc3",
      "org.msgpack"         %%  "msgpack-scala"   % "0.6.8",
      "com.livestream"      %%  "scredis"         % "1.1.2",
      "com.confabulous"     %%  "messages"        % "0.0.1-SNAPSHOT",
      "com.confabulous"     %%  "db"              % "0.0.1-SNAPSHOT"
    )
    
    packageArchetype.java_server
    
    maintainer := "Dan Ellis <dan@halftreelabs.com>"
    

    更多信息应该可以从 sbt-native-packager 文档中获得。也欢迎评论。

    【讨论】:

      猜你喜欢
      • 2014-07-03
      • 2015-08-05
      • 2016-12-27
      • 2017-03-21
      • 1970-01-01
      • 2016-10-24
      • 2014-02-22
      • 2014-09-23
      • 2014-01-27
      相关资源
      最近更新 更多