You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker化Scalapy Scala应用时遇‘Unable to load python3’错误求助

问题

我正在Docker化一个用Scalapy运行Python代码的Scala应用,Scala版本2.13.1,sbt版本1.2.8。应用在IntelliJ的sbt-shell中运行正常,但Docker化后启动容器时出现Unable to load python3错误。已确认容器内已安装Python3(路径为/usr/bin/python3),但仍报无法加载libpython3.so的UnsatisfiedLinkError,请求解决该Docker化问题。

Scala主类代码

import me.shadaj.scalapy.interpreter.CPythonInterpreter
import me.shadaj.scalapy.py

object Main extends App {
  val pythonCode =
    """
      |import os
      |
      |myFile = os.path.join("src", "main", "resources", "myFile.txt")
      |
      |with open(myFile, "w") as file:
      |    file.write("Hello World!")
      |""".stripMargin

  py.local {
    CPythonInterpreter.execManyLines(pythonCode)
  }
}

project/plugins.sbt依赖

libraryDependencies += "ai.kien" %% "python-native-libs" % "0.2.2"

build.sbt配置

import com.typesafe.sbt.packager.docker.{DockerChmodType, DockerPermissionStrategy, ExecCmd}
import ai.kien.python.Python

lazy val root = (project in file("."))
  .settings(
    name := "my-project"
  )

ThisBuild / version := "0.1.0-SNAPSHOT"

ThisBuild / scalaVersion := "2.13.1"

ThisBuild / scapegoatVersion := "1.4.0"

enablePlugins(JavaAppPackaging, DockerPlugin)
packageName in Docker:= "my-project"

version in Docker:= "0.0.3"
dockerExposedPorts:= Seq(8083)

dockerChmodType := DockerChmodType.UserGroupWriteExecute
dockerPermissionStrategy := DockerPermissionStrategy.CopyChown
dockerAdditionalPermissions += (DockerChmodType.UserGroupPlusExecute, "/var/run/")
daemonUserUid in Docker := None
daemonUser in Docker    := "root"

dockerCommands ++= Seq(
  ExecCmd("RUN", "apt-get", "update"),
  ExecCmd("RUN", "apt-get", "install", "-y", "python3")
)

fork:= true

lazy val python = Python("/usr/bin/python3")

lazy val javaOpts = python.scalapyProperties.get.map {
  case (k, v) => s"""-D$k=$v"""
}.toSeq

javaOptions ++= javaOpts

libraryDependencies ++= Seq(
  "me.shadaj" %% "scalapy-core" % "0.5.2"
)

自动生成的Dockerfile

FROM openjdk:8
WORKDIR /opt/docker
COPY --chown=root:root opt /opt
EXPOSE 8083
USER root
ENTRYPOINT ["/opt/docker/bin/notary-scraping"]
CMD []
RUN ["apt-get", "update"]
RUN ["apt-get", "install", "-y", "python3"]

报错信息

Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'python3':
libpython3.so: cannot open shared object file: No such file or directory
libpython3.so: cannot open shared object file: No such file or directory
Native library (linux-x86-64/libpython3.so) not found in resource path (...)

解决方法

1. 修复Dockerfile命令顺序问题

自动生成的Dockerfile中,Python安装命令放在了ENTRYPOINT之后,容器启动时Python还未安装。需要调整dockerCommands顺序,让安装操作在COPY之前执行,同时安装包含libpython3.so的python3-dev包:

修改build.sbt中的dockerCommands部分:

dockerCommands := Seq(
  Cmd("FROM", "openjdk:8"),
  Cmd("WORKDIR", "/opt/docker"),
  ExecCmd("RUN", "apt-get", "update"),
  ExecCmd("RUN", "apt-get", "install", "-y", "python3", "python3-dev"),
  Cmd("COPY", "--chown=root:root", "opt", "/opt"),
  Cmd("EXPOSE", "8083"),
  Cmd("USER", "root"),
  Cmd("ENTRYPOINT", "/opt/docker/bin/my-project"), // 确保与packageName一致,替换原错误的notary-scraping
  Cmd("CMD", "[]")
)

2. 创建libpython3.so软链接

容器内libpython3.so通常以版本化名称存在(如libpython3.8.so),JVM无法直接识别。添加软链接命令让JNA找到库文件:
在上述dockerCommands中添加一行:

ExecCmd("RUN", "ln", "-s", "/usr/lib/x86_64-linux-gnu/libpython3.8.so", "/usr/lib/libpython3.so")

注:可通过RUN ls /usr/lib/x86_64-linux-gnu/libpython*.so查看容器内实际的库文件名,替换对应版本号。

3. 显式指定JNA库路径

在build.sbt中添加JNA路径配置,确保JVM能定位到Python库:

javaOptions ++= javaOpts ++ Seq("-Djna.library.path=/usr/lib/x86_64-linux-gnu/")

4. 修正Python代码中的文件路径

原代码中src/main/resources/myFile.txt在Docker容器内不存在,修改为容器工作目录下的路径:

val pythonCode =
  """
    |import os
    |
    |myFile = os.path.join(os.getcwd(), "myFile.txt")
    |
    |with open(myFile, "w") as file:
    |    file.write("Hello World!")
    |""".stripMargin

内容的提问来源于stack exchange,提问作者Zaryab Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 23:05:16