Ubuntu服务器部署SpringBoot应用:Docker-Compose跨路径构建镜像时触发文件路径错误
这个错误的核心原因是Docker构建上下文的路径设置不正确,导致构建过程中找不到target/tender-api.jar文件。
为什么会出现这个错误?
当你在docker-compose.yml里设置build.context: .时,Docker会把当前执行docker compose up命令的目录作为构建上下文,将这个目录下的所有文件发送给Docker守护进程。但你的Spring Boot项目的target目录(里面有打包好的jar包)是在/root/dev/tender-api/目录下,而不是你执行docker-compose命令的当前目录,所以构建时自然找不到target文件夹。
另外,你的dockerfile路径写法也有问题:绝对路径在Docker Compose的build配置里虽然能找到Dockerfile,但上下文不对的话,Dockerfile里的COPY ${JAR_FILE} app.jar还是会基于上下文目录去寻找文件,而不是Dockerfile所在的目录。
修复步骤
1. 修正docker-compose.yml的build配置
把context设置为Dockerfile所在的项目目录(也就是你的Spring Boot项目根目录),同时dockerfile可以简化为相对路径(因为上下文已经指向项目目录了):
version: '3.8' services: appDB: image: postgres:14.1-alpine restart: always environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres ports: - '5432:5432' volumes: - db:/var/lib/postgresql/data tender: image: tender-api:1 build: context: /root/dev/tender-api # 改为Spring Boot项目的根目录 dockerfile: Dockerfile # 上下文已指向项目目录,直接写Dockerfile即可 volumes: - /data/tender-api ports: - "8080:8080" depends_on: - appDB volumes: db: driver: local
2. 确保Spring Boot项目已经打包成功
在执行docker compose up之前,先进入你的Spring Boot项目目录,执行打包命令生成jar包:
cd /root/dev/tender-api/ ./mvnw clean package # Maven项目用这个命令 # 或者 ./gradlew build # Gradle项目用这个命令
这一步不能省略——如果target目录下没有tender-api.jar,即使上下文正确,还是会报错。
3. 重新执行构建命令
回到docker-compose.yml所在的目录,执行:
docker compose up --build
加上--build参数可以强制重新构建镜像,避免使用旧的缓存导致问题。
额外优化提示
如果你不想每次都手动打包,可以用多阶段构建的Dockerfile,让Docker自动完成打包步骤,不需要提前在本地构建jar包。示例如下:
# 第一阶段:构建jar包 FROM maven:3.8.6-openjdk-11 AS builder WORKDIR /app COPY pom.xml . COPY src ./src RUN mvn clean package -DskipTests # 第二阶段:运行jar包 FROM adoptopenjdk/openjdk11:alpine-jre WORKDIR /opt/app COPY --from=builder /app/target/tender-api.jar app.jar ENTRYPOINT ["java","-jar","app.jar"]
使用这种方式的话,docker-compose的context还是指向项目目录,Docker会自动完成代码构建和jar包打包,流程更自动化。
内容的提问来源于stack exchange,提问作者yahoo

