
本文详解如何在 GitLab CI 流水线中可靠传递 Maven 构建产物(如 *-exec.jar)至后续 Docker 构建阶段,解决因工作目录隔离导致的 lstat /target: no such file or directory 错误。核心在于显式声明 artifacts 并合理配置路径。
本文详解如何在 gitlab ci 流水线中可靠传递 maven 构建产物(如 *-exec.jar)至后续 docker 构建阶段,解决因工作目录隔离导致的 lstat /target: no such file or directory 错误。核心在于显式声明 artifacts 并合理配置路径。
在 GitLab CI 中,每个 job 默认运行在独立的临时容器环境中,彼此之间不共享文件系统。这意味着 maven-build 阶段生成的 target/ 目录(含可执行 JAR)不会自动出现在 docker-build 阶段的工作目录里——这正是报错 lstat /var/lib/docker/tmp/.../target: no such file or directory 的根本原因。GitLab 不会自动“猜”你要传递哪些构建产物;必须通过 artifacts 显式声明并持久化。
✅ 正确做法:在 maven-build job 中明确定义 artifacts,将目标 JAR 文件作为制品上传:
maven-build:
image: maven:3.6.3-jdk-8
stage: build
script: "mvn $MAVEN_CLI_OPTS clean deploy -e"
artifacts:
paths:
- target/*-exec.jar # ✅ 推荐:相对路径,更安全(无需 $CI_PROJECT_DIR)
expire_in: 1 week # 可选:自动清理过期制品⚠️ 注意事项:
Git Worktree 多需求并行开发助手:在当前 worktree 目录独立开发、修改、提交代码,不跨目录。基于目录命名规范自动识别仓库归属(如 main-repo-feature‑a → main‑repo 仓库)。遵循最小改动原则,从需求分析到 commit 交付全流程负责。触发场景:用户在 ...
-
路径必须为相对路径:
artifacts.paths中应使用target/xxx.jar而非绝对路径$CI_PROJECT_DIR/target/xxx.jar。GitLab 会自动在当前 job 工作目录下查找。 -
通配符需谨慎:
*-exec.jar依赖项目实际输出命名(如hello-spring-boot-exec.jar)。若不确定,可先用ls -l target/在script中调试,或改用精确名称target/hello-spring-boot-exec.jar。 -
Dockerfile 同步更新:确保
Dockerfile中COPY指令与实际产物名一致:FROM openjdk:8-jre-slim COPY target/hello-spring-boot-exec.jar /app.jar # ✅ 与 artifacts 和 mvn 输出严格匹配 ENTRYPOINT ["java", "-jar", "/app.jar"] EXPOSE 7001
? 进阶优化建议:
-
启用
needs显式依赖(GitLab 12.2+):避免隐式阶段顺序,提升可读性与调试效率:docker-build: stage: package needs: ["maven-build"] # ✅ 明确声明依赖关系 script: - docker info - docker build -t gitlab.my-domain.local:5000/spring-boot-hello-world:$CI_COMMIT_TAG . - docker push gitlab.my-domain.local:5000/spring-boot-hello-world:$CI_COMMIT_TAG -
镜像标签语义化:避免硬编码
latest,改用$CI_COMMIT_TAG或$CI_COMMIT_SHORT_SHA,保障可追溯性与生产稳定性(参考《Docker 标签命名规范》)。 -
安全加固:
docker-buildjob 应使用docker:dind(Docker-in-Docker)服务而非仅image: docker:stable,并启用 TLS(推荐docker:24.0.0-dind+DOCKER_TLS_CERTDIR)。
总结:GitLab CI 的制品传递不是“默认行为”,而是需主动设计的契约。artifacts 是连接构建与打包阶段的桥梁——缺失它,Docker 构建便成了无源之水。从今天起,请把 artifacts 视为 Java 容器化流水线的必需字段,而非可选项。

















