Quarkus+Angular JVM镜像部署Kubernetes后前端404问题排查
一、导致前端404的遗漏配置排查
1. SPA路由转发配置缺失
Quarkus开发模式(quarkus:dev)会自动处理单页应用(SPA)的路由转发,但生产模式需要显式配置。添加以下配置到application.properties:
# 配置SPA根路径为应用根目录 quarkus.http.spa.root=/ # 指定SPA入口文件为index.html quarkus.http.spa.index-path=/index.html
该配置会将所有未匹配到静态资源或后端API的请求,重定向到index.html,解决Angular子路由刷新或直接访问时的404问题。
2. Angular构建未指定正确的base-href
如果Kubernetes部署时应用带有上下文路径(如Ingress配置了/my-app前缀),Angular构建时未设置对应base-href会导致资源加载路径错误。构建Angular时执行:
ng build --base-href /my-app/
若应用无上下文路径,可设置为相对路径避免路径问题:
ng build --base-href ./
3. Kubernetes Ingress路径配置不匹配
如果使用Ingress路由到应用,需确保Ingress的路径重写规则与Angular的base-href一致。例如,若Ingress配置了路径前缀/my-app,需添加重写注解:
annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2
同时Ingress的路径规则应设置为:
paths: - path: /my-app(/|$)(.*) pathType: Prefix backend: service: name: your-quarkus-service port: number: 8080
4. 静态资源打包路径验证
虽然你确认jar包含前端文件,但需验证文件是否在BOOT-INF/classes/META-INF/resources目录下(Quarkus JVM打包的静态资源默认加载路径)。可通过jar tf your-app.jar命令查看目录结构,确保前端文件位于该路径下。
二、替代双镜像部署的优方案
1. 使用Quarkus Frontend Maven插件自动化构建
通过quarkus-frontend-maven-plugin自动集成Angular构建流程,无需手动复制构建产物。在pom.xml中添加插件配置:
<plugin> <groupId>io.quarkus</groupId> <artifactId>quarkus-frontend-maven-plugin</artifactId> <version>${quarkus.version}</version> <executions> <execution> <id>frontend-build</id> <phase>process-resources</phase> <goals> <goal>build</goal> </goals> <configuration> <nodeVersion>20.10.0</nodeVersion> <packageJsonPath>src/main/angular/package.json</packageJsonPath> <buildCommand>ng build --prod --base-href ./</buildCommand> <distDir>dist/angular-app</distDir> <outputDirectory>${project.build.outputDirectory}/META-INF/resources</outputDirectory> </configuration> </execution> </executions> </plugin>
执行mvn package时,插件会自动安装Node、构建Angular并将产物复制到正确目录,简化构建流程。
2. 多阶段Docker镜像构建
采用多阶段构建减少镜像体积,同时确保前后端产物正确整合:
# 第一阶段:构建Angular前端 FROM node:20-alpine AS frontend-builder WORKDIR /app COPY src/main/angular/package*.json ./ RUN npm ci COPY src/main/angular/ . RUN ng build --prod --base-href ./ # 第二阶段:构建Quarkus后端 FROM quay.io/quarkus/quarkus-jvm-builder-image:2.16-java17 AS backend-builder WORKDIR /project COPY pom.xml . COPY src/main/java ./src/main/java COPY src/main/resources ./src/main/resources # 复制前端构建产物到后端资源目录 COPY --from=frontend-builder /app/dist/angular-app ./src/main/resources/META-INF/resources RUN mvn package -DskipTests # 最终镜像:运行Quarkus应用 FROM quay.io/quarkus/quarkus-runtime-image:2.16-java17 WORKDIR /deployments COPY --from=backend-builder /project/target/quarkus-app/lib/ ./lib/ COPY --from=backend-builder /project/target/quarkus-app/*.jar ./ COPY --from=backend-builder /project/target/quarkus-app/app/ ./app/ COPY --from=backend-builder /project/target/quarkus-app/quarkus/ ./quarkus/ EXPOSE 8080 CMD ["java", "-jar", "./quarkus-run.jar"]
该方式分离构建环境与运行环境,最终镜像仅包含运行所需依赖,体积更小。
3. 打包为Quarkus Native镜像
若追求极致性能,可将应用打包为Native镜像,启动速度更快、资源占用更低。只需添加native profile构建:
mvn package -Pnative
同时确保application.properties中已配置SPA路由,Native模式下同样支持静态资源加载与路由转发。
内容的提问来源于stack exchange,提问作者Danilo Körber

