非root用户运行Docker镜像报无法创建Maven本地仓库错误
报错原因
这个报错是Maven本地仓库路径权限不足导致的:
- 你使用
useradd -r创建系统用户时,没有加-m参数,命令不会自动创建/home/myuser家目录,Maven默认要在~/.m2/repository路径下写入依赖缓存,对应父目录根本不存在,自然无法创建仓库目录。 - 你在Dockerfile中只给
/app目录做了属主变更,完全没有处理Maven运行需要的家目录路径权限,就算手动创建了/home/myuser目录,默认属主是root,普通用户myuser也没有写入权限。
另外你写的RUN chmod -R 700 run.sh后面又跟了USER myuser之后的RUN chmod u+x run.sh是完全多余的操作,root用户给run.sh设置700权限且属主为myuser时,myuser本身就已经有执行权限,重复授权没有意义。
修复方法
两种方案任选其一即可:
方案1:创建用户时自动生成家目录(推荐)
创建用户时加上-m参数让系统自动生成家目录并分配正确权限,调整后的Dockerfile如下:
FROM maven:3.6-jdk-11-slim WORKDIR /app COPY . . # 提前指定Maven本地仓库路径,方便后续复用构建阶段的依赖缓存 RUN mvn clean dependency:go-offline -Dmaven.repo.local=/app/.m2/repository # 创建用户组和用户,-m参数自动创建用户家目录 RUN groupadd -r -g 2000 mygrp && useradd -m -u 2000 -r -g mygrp myuser # 给应用目录和Maven仓库目录分配属主 RUN chown -R myuser:mygrp /app RUN chmod 700 run.sh USER myuser ENTRYPOINT ["./run.sh"]
对应修改run.sh,指定和构建阶段一致的Maven仓库路径,复用已经下载好的依赖,避免启动时重复拉取:
mvn clean spring-boot:run -Dmaven.repo.local=/app/.m2/repository
方案2:跳过家目录配置,直接指定Maven仓库到有权限的路径
如果不想创建用户家目录,可以直接把Maven本地仓库指定到/app目录下的路径——你已经给/app分配了myuser的读写权限,不需要额外处理家目录。只需要修改run.sh内容即可:
mvn clean spring-boot:run -Dmaven.repo.local=/app/.m2/repository
如果要复用构建阶段下载的依赖,记得在构建阶段执行maven命令时也加上相同的-Dmaven.repo.local参数,同时给对应路径分配myuser的属主权限。
额外优化建议
生产环境不建议直接用mvn spring-boot:run启动服务,更好的实践是在构建阶段用Maven把项目打包成可执行jar包,之后切换到精简的JRE基础镜像运行jar包,不需要在运行时容器中保留Maven等构建工具,既能缩小镜像体积,也能降低攻击面。
内容的提问来源于stack exchange,提问作者Jae
相关产品推荐
相关产品推荐

