【问题标题】:Building Scala project with docker's Multi-Stage使用 docker 的 Multi-Stage 构建 Scala 项目
【发布时间】:2021-04-11 11:55:50
【问题描述】:

我正在尝试构建一个具有 docker Multi-Stage 能力的 scala 项目。

首先,这是我的 dockerfile:

FROM maven:3.6.0-jdk-11-slim AS maven
RUN apt-get update
WORKDIR /build
COPY pom.xml .
RUN mvn -B de.qaware.maven:go-offline-maven-plugin:resolve-dependencies
COPY src src
RUN mvn -B -o install spring-boot:repackage

FROM openjdk:11.0.6
WORKDIR /opt/app
COPY --from=maven /build/target/app.jar app.jar
CMD ["java", "-jar", "/opt/app/app.jar"]
EXPOSE 8080

我注意到在完成 resolve-dependencies 部分后,maven 仍然尝试在安装阶段下载依赖项。我得到的错误与 scala-maven-plugin 有关,该插件正在寻找在解析阶段未获取的不存在的依赖项。错误如下所示:

未能执行目标 net.alchim31.maven:scala-maven-plugin:3.4.0:compile (default) on 项目应用程序:包装: org.apache.maven.artifact.resolver.ArtifactNotFoundException:不能 访问...在 离线模式和神器 org.scala-lang:scala-compiler:jar:2.11.12 尚未从 以前的。

即使添加此依赖项也不够,因为它在其他依赖项上失败。

POM 中的插件长这样:

        <plugin>
            <groupId>net.alchim31.maven</groupId>
            <artifactId>scala-maven-plugin</artifactId>
            <version>3.4.0</version>
            <executions>
                <execution>
                    <goals>
                        <!-- Need to specify this explicitly, otherwise plugin won't be called when doing e.g. mvn compile -->
                        <goal>compile</goal>
                        <goal>testCompile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <args>
                    <!-- work-around for https://issues.scala-lang.org/browse/SI-8358 -->
                    <arg>-nobootcp</arg>
                    <arg>-Yresolve-term-conflict:package</arg>
                </args>
                <scalaVersion>${scala.version}</scalaVersion>
            </configuration>
        </plugin>

似乎插件并没有停止并再次下载所有内容。 谢谢各位。。

【问题讨论】:

  • 为什么要构建maven?为什么要在 docker 内部构建?看起来像 x/y 问题
  • @cchantep 我在 docker 内部构建以利用多阶段功能来避免每次构建时下载所有库。对于 maven 部分 - 为什么不使用 maven?
  • 问题不在于多级,而在于 docker 本身。在内部构建会增加显着的开销,这对于增量构建来说是很少能接受的。至于 maven ... SBT 是 Scala 的第一个公民构建工具 ...

标签: scala maven build dependencies offline


【解决方案1】:

最后,为了解决这个问题,我将这个插件用于“离线”而不是 maven 的:

        <plugin>
            <groupId>de.qaware.maven</groupId>
            <artifactId>go-offline-maven-plugin</artifactId>
            <version>1.2.8</version>
        </plugin>

在这个命令中使用它:

mvn -B de.qaware.maven:go-offline-maven-plugin:resolve-dependencies

还添加到 scala-maven-plugin 这个配置来禁用增量编译依赖:

        <configuration>
            <recompileMode>all</recompileMode>
        </configuration>

所以完整的插件看起来像这样:

    <plugin>
        <groupId>net.alchim31.maven</groupId>
        <artifactId>scala-maven-plugin</artifactId>
        <version>4.4.0</version>
        <executions>
            <execution>
                <goals>
                    <goal>compile</goal>
                    <goal>testCompile</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <recompileMode>all</recompileMode>
        </configuration>
    </plugin>

【讨论】:

    【解决方案2】:

    就像对您的问题的评论一样,最好使用sbt 作为Scala 的第一个公民构建工具。特别是我建议将sbt-native-packager 与插件JavaAppPackagingDockerPlugin 结合使用来创建没有Dockerfile 的docker 映像。有some tutorials在网上创建。基本上,您将需要在您的 build.sbt 文件中使用类似这些行的内容(来自 my project 的示例)。

    enablePlugins(JavaAppPackaging, JavaServerAppPackaging, DockerPlugin, AshScriptPlugin)
    
    // ####### Dockerfile settings #######
    import NativePackagerHelper._
    
    packageName in Docker := packageName.value
    version in Docker := version.value
    dockerExposedPorts := List(8001, 2551)
    dockerLabels := Map("user" -> "you.email@gmail.com")
    dockerBaseImage := "openjdk:jre-alpine"
    dockerRepository := Some("docker.user.name")
    defaultLinuxInstallLocation in Docker := "/usr/local"
    daemonUser in Docker := "daemon"
    mappings in Universal ++= directory( baseDirectory.value / "src" / "main" / "resources" )
    // ####### Dockerfile settings #######
    

    project/plugins.sbt 文件中:

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

    然后您在控制台上执行以下命令,以便在 target/docker/stage/Dockerfile 创建 Dockerfile

    sbt docker:stage
    sbt docker:publishLocal
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-12
      • 2022-11-22
      • 1970-01-01
      • 1970-01-01
      • 2015-12-22
      • 2019-09-20
      • 2018-01-13
      • 2015-08-13
      相关资源
      最近更新 更多