使用 docker 的多阶段构建 Scala 项目

Building Scala project with docker's Multi-Stage

我正在尝试构建一个具有 docker 多阶段能力的 Scala 项目。

首先,这是我的docker文件:

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 有关,它寻找在解析阶段没有获取的不存在的依赖项。错误如下所示:

Failed to execute goal net.alchim31.maven:scala-maven-plugin:3.4.0:compile (default) on project app: wrap: org.apache.maven.artifact.resolver.ArtifactNotFoundException: Cannot access ... in offline mode and the artifact org.scala-lang:scala-compiler:jar:2.11.12 has not been downloaded from it before.

即使添加这个依赖项也是不够的,因为它在另一个依赖项上失败了。

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>

似乎插件并没有就此停止并重新下载所有内容。 谢谢大家..

就像对您的问题发表评论一样,最好使用 sbt 作为 Scala 的第一个公民构建工具。特别是我建议使用 sbt-native-packager in conjunction with the plugins JavaAppPackaging and DockerPlugin to create the docker image without a Dockerfile. There are some tutorials to create it on the web. Basically, you will need something like these lines on your build.sbt file (example from 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

最后,为了解决这个问题,我将这个插件用于 'go-offline' 而不是 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>