docker-compose启动容器报Unable to access jarfile错误排查求助
问题原因
这个报错和文件权限、路径拼写无关,是Mac系统下Docker Desktop单文件挂载的已知缺陷导致的:
- 你采用了直接把宿主机单个jar文件挂载到容器内的配置,Mac上Docker的文件共享模块(osxfs/virtiofs)对单文件bind mount的支持存在bug:当宿主机的jar包被maven重新构建覆盖后,容器内的挂载句柄会失效。此时你在容器内执行
ls命令只能看到挂载初始同步的文件元数据(文件名、权限、大小都显示正常),但实际文件内容的磁盘块映射已经断开,Java进程读取文件内容时会触发IO错误,直接抛出"Unable to access jarfile"。 - openjdk:11镜像没有对Mac Docker的虚拟文件系统做特殊兼容,会把这种元数据正常、内容不可读的挂载项判定为无效文件,和你写的相对路径/绝对路径启动方式没有关系。
解决方案
按实用性排序:
- 优先用目录挂载替代单文件挂载,这是最稳定的本地开发方案
修改docker-compose.yml的volumes和command配置,直接挂载整个target目录,避免单文件挂载的句柄失效问题:
修改完成后先执行version: "3.7" services: book-api: image: openjdk:11 container_name: book-api volumes: - ./target:/app command: ["java","-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8080","-Dspring.profiles.active=local","-jar","/app/demo-0.0.1-SNAPSHOT.jar"] ports: - "8080:8080"docker-compose down删除旧容器,再执行docker-compose up即可正常启动,后续本地重新打包也不会出现挂载失效问题。 - 生产环境建议直接把jar包构建进镜像,彻底绕开挂载问题
在项目根目录新建Dockerfile:
调整docker-compose.yml配置,去掉jar包相关的volumes挂载,将image改为build当前目录即可,不存在文件系统兼容问题。FROM openjdk:11 COPY ./target/demo-0.0.1-SNAPSHOT.jar /app.jar ENTRYPOINT ["java","-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8080","-Dspring.profiles.active=prod","-jar","/app.jar"] - 临时修复方案(不推荐长期用):如果一定要保留单文件挂载配置,先退出当前容器,打开Docker Desktop设置->Resources->File Sharing,确认项目所在的根目录已经加入共享列表,执行
docker-compose down -v清空所有挂载缓存后再重启容器。注意只要本地重新构建jar包覆盖原文件,这个问题会再次出现。
内容的提问来源于stack exchange,提问作者Rahul Raj
相关产品推荐
相关产品推荐

