如何加快docker中sbt scala的构建速度?

时间:2019-01-17 04:37:46

标签: scala docker build sbt libraries

我的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下载库中进行缓存可能有相同的技巧吗?

2 个答案:

答案 0 :(得分:1)

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

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

RUN cmd1 \
  && cmd2 \
  && cmd3

为什么要为每个版本构建映像?这似乎很浪费。通常,您是在Docker映像之外构建内容的,只打包结果。

我的建议是使用sbt-native-packager SBT插件及其Docker integration来在构建伪影后简单地从伪影构建图像。这样,您只需要映像中的JRE,而不是JDK,而不是SBT。另外,启动图像时无需等待SBT初始化。

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

答案 1 :(得分:1)

您可以参考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可以与您现在使用的相同(当然,您可以简化它,只需添加jackson库在build.sbt中定义,目标只是希望.ivy2有杰克逊库),然后例如将其标记为mybaseimage:v1

然后,新项目的Dockerfile可以使用base mybaseimage:v1,因为mybaseimage已经在.ivy2.sbt中拥有该库,因此无需再次下载jackson每次您构建项目的Dockerfile时。

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