【问题标题】:SBT project not mounted to Docker container using docker-composeSBT 项目未使用 docker-compose 安装到 Docker 容器
【发布时间】:2020-08-14 18:00:41
【问题描述】:

当我运行docker-compose up --build 时,DB 容器运行良好,但应用容器存在

[error] java.lang.RuntimeException: No main class detected.
[error]     at scala.sys.package$.error(package.scala:30)
[error] stack trace is suppressed; run 'last Compile / bgRun' for the full output
[error] (Compile / bgRun) No main class detected.
[error] Total time: 3 s, completed Apr 30, 2020 10:07:31 AM
ERROR: Service 'app' failed to build: The command 'sbt run' returned a non-zero code: 1

我的 Dockerfile:

FROM        hseeberger/scala-sbt:8u222_1.3.5_2.13.1
MAINTAINER  <HIDDEN>
EXPOSE      8080 8000

WORKDIR     /www/app

VOLUME /www/app

RUN ["sbt", "run"]

我的 docker-compose.yml:

version: "3.3"
services:
  db:
    image: postgres:latest
    ports:
      - "5432:5432"
  app:
    build: .
    ports:
     - "8080:8080"
     - "8000:8000"
    volumes:
     - ..:/www/app

我的 Scala 项目结构:

Main.scala 只包含一个超级简单的Hello World,如您所见:

object Main extends App {
  println("Hello from main scala object")
}

如果我在Dockerfile 中使用RUN ["sbt"] 运行容器,则容器保持运行。我通过docker exec -it adcc9897d1fc bash 连接,可以看到/www/app 文件夹是空的(除了sbt 创建的文件夹)。知道为什么它是空的并且不包含项目吗?

【问题讨论】:

    标签: scala docker docker-compose sbt dockerfile


    【解决方案1】:

    在考虑 docker-compose.yml 文件中的大多数其他选项之前,会先考虑和处理 Dockerfile。特别是镜像构建永远不会从 Docker Compose 设置中看到 volumes:(它也看不到 environment: 变量或任何与网络相关的设置,包括 default 网络)。

    这意味着,在构建时(因为它是一个RUN 指令),您正试图在一个空的匿名卷上运行sbt run。这会产生您遇到的“无主类”错误。

    对于基于 JVM 的语言,典型设置是在主机上编译应用程序,然后将 COPY(便携式).jar 文件放入您的映像中。 sbt-native-packager插件其实可以do all of this for you;如果您更喜欢手动操作,sbt-assembly plugin 可以生成一个“胖”.jar,其中包含应用程序的所有依赖项。然后,您将获得典型的最小 JVM Dockerfile

    FROM openjdk:8
    COPY target/scala-2.13/my-app-*.jar /my-app.jar
    CMD ["java", "-jar", "/my-app.jar"]
    

    如果要在 Dockerfile 中编译应用程序,则需要将应用程序放入 COPY,并设置 CMD 以在容器启动时(而不是在构建期间)运行应用程序。

    FROM hseeberger/scala-sbt:8u222_1.3.5_2.13.1
    WORKDIR /www/app
    
    # Copy the application source in.
    COPY ./ ./
    
    # Build it.
    RUN sbt compile
    
    # Set the command to run and other metadata when the container starts.
    EXPOSE 8000 8080
    CMD sbt run
    

    (您也可以使用multi-stage build 来组合这两个Dockerfile:首先COPY 源树和sbt compile 它,然后在第二阶段COPY --from=build 仅将jar 文件转换为仅JRE 映像.)

    由于COPY 指令,您需要将构建上下文设置为源代码树的根。 (将Dockerfiledocker-compose.yml 移动到build.sbt 文件旁边的存储库根目录可能更容易。)

    version: "3.3"
    services:
      app:
        build:
          context: ..
          dockerfile: docker/Dockerfile
        ports:
         - "8080:8080"
         - "8000:8000"
        # No need for volumes:, source code is already in the image
    

    原则上,您可以将应用程序代码绑定挂载到问题中,sbt run 命令将重新编译它。在 Dockerfile 中不需要 VOLUME 指令。您可能会发现在主机 JDK/sbt 环境中进行日常开发会更容易。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-01
      • 2020-05-16
      • 2022-11-21
      相关资源
      最近更新 更多