【问题标题】:How to speed up sbt scala build in docker?如何加快 sbt scala 在 docker 中的构建速度?
【发布时间】:2019-06-11 06:03:11
【问题描述】:

我有 docker 文件:

FROM amazonlinux:2017.03

ENV SCALA_VERSION 2.11.8
ENV SBT_VERSION 0.13.13

# Install Java8 
RUN yum install -y java-1.8.0-openjdk-devel

# Install Scala and SBT
RUN yum install -y https://downloads.lightbend.com/scala/2.11.8/scala-2.11.8.rpm
RUN yum install -y https://dl.bintray.com/sbt/rpm/sbt-0.13.13.rpm
RUN sbt sbtVersion

COPY . /root  
WORKDIR /root  

# Exposing port 80
EXPOSE 80

RUN sbt compile
CMD sbt run

和sbt配置文件有:

name := "hello"

version := "1.0"

scalaVersion := "2.11.8"

libraryDependencies += "com.fasterxml.jackson.core" % "jackson-databind" % "2.9.5"
libraryDependencies += "com.fasterxml.jackson.module" % "jackson-module-scala_2.11" % "2.9.5"

每次我构建 docker container sbt 时都会重新下载 jackson 库。我怎样才能加快这个过程,可以在编译之前执行部分 sbt 文件。

在我将RUN sbt sbtVersion 添加到 Dockerfile 之前,sbt 已经完全下载,并且在我添加此命令之后,每次构建 docker 容器时都已缓存并且不会运行。

在 sbt 中下载库的 docker 中缓存可能有相同的技巧吗?

【问题讨论】:

    标签: scala docker build sbt libraries


    【解决方案1】:

    首先,您不需要安装 scala RPM,因为 SBT 本身会为您下载 Scala(无论您的构建中配置了哪个版本)。

    其次,每个RUN 命令都会创建一个您通常要避免的新层。合并它们:

    RUN cmd1 \
      && cmd2 \
      && cmd3
    

    为什么要为每个构建构建一个映像?这似乎很浪费。通常你在 Docker 镜像之外构建你的东西​​并且只打包结果。

    我的建议是使用带有 Docker integration 的 sbt-native-packager SBT 插件,以便在构建它们之后从您的人工制品中简单地构建一个图像。这样,您的映像中只需要一个 JRE,而不是 JDK,也不需要 SBT。此外,启动映像时无需等待 SBT 初始化。

    如果您安装了新的 Docker 版本,您可以使用 multi-stage builds

    【讨论】:

    • 我阅读了 SBT 插件并尝试在 docker 中构建 https://github.com/tumblr/colossus 但无法做到。我跑了: sbt "project colossus-examples" docker:publishLocal 但它没有用。我哪里错了?
    • 如果没有看到错误就很难判断。看看这里:github.com/avdv/colossus/tree/docker,这会构建一个colossus-examples:0.11.0 图像,可以以docker run --rm -p 9001:9001 colossus-examples:0.11.0 开头。
    【解决方案2】:

    可以参考travis的解决方案:

    .travis.yaml:

    # These directories are cached to S3 at the end of the build
    cache:
      directories:
        - $HOME/.ivy2/cache
        - $HOME/.sbt/boot/
    

    Travis 会将以上两个文件夹备份到 s3 中,然后每次用户重新构建之前,都会从缓存中获取这两个文件夹。

    因此,我们可以知道您不再下载jackson library 的可能方法可以将.ivy2.sbt 文件夹分开,并将它们放在类似缓存的地方。

    对于您的情况,我认为最好的解决方案是将这些存储在基础映像中,基础映像的Dockerfile 可以与您现在使用的相同(当然,您可以简单,只需添加杰克逊库定义在 build.sbt 中,目标只是希望.ivy2 有杰克逊库),然后例如将其标记为 mybaseimage:v1

    那么你的新项目的 Dockerfile 可以使用base mybaseimage:v1,因为mybaseimage 已经在.ivy2&.sbt 中有库,所以每次构建项目的 Dockerfile 时都不需要再次下载jackson

    该解决方案可能很难看,但我认为可以作为一种解决方法,仅供参考。

    【讨论】:

    • 即我需要用这个库在另一个目录中构建虚拟项目,然后以某种方式使用这个构建的容器作为“父”容器,并以某种方式在其中添加构建我的项目作为第二阶段?
    • 是的,我想是的。如果 docker 有一些现有的解决方案来做到这一点,我猜travis 不会找到自己的解决方法来做到这一点,这很丑陋,但我没有看到任何其他解决方案。您可以等待,看看是否有其他更好的答案。
    猜你喜欢
    • 1970-01-01
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    • 2011-07-04
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多