PAYATHON 2026

Apple Silicon Mac 上如何用 Docker 运行 Spring Boot 项目?

数据小陈

先确认构建失败在哪一步

可以使用 Docker Desktop 在本机运行 Spring Boot 应用。由于缺少 docker build 的错误输出,目前还不能确定具体的失败原因。

给出的 Dockerfile 中有两处需要优先检查:

  • RUN addgroup -S spring && adduser -S spring -G spring:这组参数常见于 Alpine 环境,不能直接假定其他基础镜像也支持。
  • ARG JAR_FILE=target/*.jar:构建镜像前,必须先生成可执行 JAR,并确保该路径只匹配一个目标文件。

Apple Silicon 的镜像架构兼容性也需要检查,但要看到相关报错,才能判断它是否是这次失败的原因。

1. 获取完整的构建日志

在包含 Dockerfile 的项目目录中执行:

docker build --progress=plain -t springio/gs-spring-boot-docker .

原问题写到“得到以下结果”,但没有附上结果。排查时应保留失败步骤及其前后的完整错误信息。

根据失败位置,可以先检查以下问题:

失败位置优先检查
FROM 或加载基础镜像元数据镜像标签、镜像仓库访问、平台支持
RUN addgroup ...基础镜像中的命令及参数是否可用
COPYJAR 是否存在、路径和构建上下文是否正确
容器启动后退出JAR 是否可执行、Java 版本、应用配置和依赖服务

2. 先用 Maven 生成可执行 JAR

当前 Dockerfile 只负责复制 JAR,不会执行 Maven 打包。

如果项目带有 Maven Wrapper,在项目根目录运行:

./mvnw clean package

如果没有 Wrapper,但本机已经安装 Maven,则运行:

mvn clean package

打包成功后检查产物:

ls -lh target/*.jar

需要复制的是能通过 java -jar 启动的 Spring Boot JAR。如果启动时报 no main manifest attribute,应检查 Spring Boot Maven 插件是否配置了可执行 JAR 的重新打包,此时无需继续修改 Docker 用户配置。

还要检查 .dockerignore。如果它排除了 target/ 或目标 JAR,文件即使在本机存在,也无法被 COPY 使用。

3. 避免依赖基础镜像的用户创建命令

如果日志确认失败在 addgroup 或 adduser,可以改用数字 UID/GID,省去对这两个命令的依赖。

下面的示例保留了原来的基础镜像。使用前需要确认 openjdk:25-oracle 标签能够拉取、支持所选平台,并且其中的 Java 运行时适合项目;原始信息不足以确认这些条件。

FROM openjdk:25-oracle

WORKDIR /app

ARG JAR_FILE=target/*.jar
COPY --chown=10001:10001 ${JAR_FILE} app.jar

USER 10001:10001

ENTRYPOINT ["java","-jar","/app/app.jar"]

USER 10001:10001 指定运行进程的 UID/GID,不需要先创建名为 spring 的用户。COPY --chown 则把 JAR 的所有者和所属组设为同一组 ID。

如果应用依赖用户名查询、用户主目录或特定目录的写权限,还需要根据实际基础镜像配置用户和目录权限。这份示例只覆盖基本的 JAR 启动场景。

明确指定要复制的 JAR

target/*.jar 只有在恰好匹配一个 JAR 时才适合当前写法。如果同时生成主 JAR、sources JAR 等多个文件,应该明确指定应用 JAR:

docker build --progress=plain \
  --build-arg JAR_FILE=target/your-app.jar \
  -t springio/gs-spring-boot-docker .

将 target/your-app.jar 替换成实际生成的文件路径。该路径相对于命令末尾 . 所指定的构建上下文。

4. 根据报错检查 Apple Silicon 兼容性

如果错误包含 no matching manifest,应检查所选基础镜像是否提供当前平台对应的镜像。

如果出现 exec format error,应进一步检查镜像或其中可执行文件的架构。

优先选择与项目 Java 要求相符、提供 linux/arm64 镜像的基础镜像。不要仅凭 Dockerfile 中的注释,就认定 Java 17 一定适合这个项目。

只有在确认镜像提供 linux/amd64 版本、确实需要运行该版本,并且 Docker Desktop 支持相应模拟运行时,才考虑显式指定平台:

docker build --platform=linux/amd64 \
  -t springio/gs-spring-boot-docker .

模拟运行可能带来性能开销,也无法解决错误的用户创建参数或缺失的 JAR。

5. 启动容器并检查应用日志

镜像构建成功后,如果应用在容器内监听 8080,可以运行:

docker run --rm --name spring-web \
  -p 8080:8080 \
  springio/gs-spring-boot-docker

然后访问 http://localhost:8080,并使用项目实际提供的接口路径测试。根路径没有映射时,返回 404 不代表容器启动失败。

如果应用使用其他端口,应相应调整 -p 宿主机端口:容器端口。应用也需要监听容器可对外访问的地址;若配置为只监听容器内的 127.0.0.1,端口映射无法正常提供访问。

前台运行会直接显示 Spring Boot 日志。如果容器启动后退出,应根据日志检查 Java 版本、配置文件、数据库连接等应用问题。

IntelliJ IDEA 可以继续用于开发和执行 Maven 任务。先在终端完成打包、镜像构建和容器启动,有助于定位失败环节。流程跑通后,再将相同配置接入 IDE。

备注:内容仅供参考。