sbt 原生打包器 dockerCommands 复制

Posted

技术标签:

【中文标题】sbt 原生打包器 dockerCommands 复制【英文标题】:sbt native packager dockerCommands copy 【发布时间】:2018-10-19 14:26:10 【问题描述】:

在互联网和此处搜索,但找不到解决我问题的答案。

我的问题是我想创建一个 docker 镜像,其中包含一些从本地文件系统复制到 docker 镜像的自定义 sql 脚本。

目录结构(一个多模块项目)是

my_sbt
    + my_app
        - build.sbt ...
    + database
        - build.sbt 
        + scripts
            - ... several sql scripts ...

database/build.sbt 包含 dockerCommands

dockerCommands := Seq(
  Cmd("FROM", "postgres:9.5"),
  Cmd("EXPOSE", "5432"),
  Cmd("COPY", (baseDirectory.value / "database" / "scripts" / "a.sql").toPath.toAbsolutePath.toString, "/docker-entrypoint-initdb.d/a.sql")
)

如果没有 COPY Cmd,图像可以成功创建(即docker run -d --rm -p 5432:5432 <docker image> 启动容器,docker exec -it <container id> bash 可以 bash 到容器并验证处理是否由容器 bash 中的 ps -ef 运行)。但是,将 COPY 语句添加到 dockerCommands 会使构建过程 sbt docker:publishLocal 崩溃,并出现错误 java.lang.RuntimeException: Nonzero exit value: 1

java.lang.RuntimeException: Nonzero exit value: 1
    at com.typesafe.sbt.packager.docker.DockerPlugin$.publishLocalDocker(DockerPlugin.scala:335)
    at com.typesafe.sbt.packager.docker.DockerPlugin$$anonfun$projectSettings$22.apply(DockerPlugin.scala:119)
    at com.typesafe.sbt.packager.docker.DockerPlugin$$anonfun$projectSettings$22.apply(DockerPlugin.scala:117)
...

使用 -d sbt -d docker:publishLocal 运行 sbt 没有帮助,因为它仍然抛出 Nonzero exit value: 1,这根本没有帮助。

引用本地脚本并复制到docker镜像的正确方法是什么?

谢谢

编辑:

请注意,sbt 本机打包程序似乎去掉了前导根路径,即“/”。有什么理由这样做吗?以及如何防止导致/从剥离?

[info] Step 3/3 : COPY /path/to/database/scripts/users.sql /docker-entrypoint-initdb.d/users.sql
[error] lstat path/to/database/scripts/users.sql: no such file or directory

【问题讨论】:

【参考方案1】:

https://serverfault.com/questions/666149/docker-copy-issue-no-such-file-or-directory/666154#666154 的链接解决了我的问题。

基本上问题来自于 docker 将本地文件关联到 docker 容器的间接方式。

    sbt native packager 根据映射在 Universal 部分复制本地文件到 target/docker/stage。比如下面的代码sn -p 拷贝a.sql到项目目录下的target/docker/stage/opt/docker/scripts

    mappings in Universal := 
      (mappings in Universal).value :+
      (file(s"$baseDirectory.value/scripts/a.sql") -> "scripts/a.sql") 
    
    

    sbt 原生打包程序然后根据 dockerCommandsCmd("COPY", "/opt/docker/scripts/a.sql", "/docker-entrypoint-initdb.d")

    将位于 target/docker/stage/ 的文件复制到 docker 容器

所以 The <src> path must be inside the context of the build; ... 上下文实际上是从 target/docker/stage/ 开始的。

【讨论】:

以上是关于sbt 原生打包器 dockerCommands 复制的主要内容,如果未能解决你的问题,请参考以下文章

Sbt 本机打包程序不创建服务脚本文件

使用 sbt 原生打包将 fat jar 打包成 debian

SBT 原生打包程序:在 %install 中解压缩工件

设置 sbt 程序集 v0.14.2 的问题

问题:sbt打包出错--Spark打包编译出错

将 docker 插件与 sbt 一起使用