Jenkins Docker-in-Docker构建中Docker Build失败原因及解决办法
/proc/1/map_files权限错误 错误原因
当你在Jenkins的Docker-in-Docker(dind)环境里运行find /这种遍历整个根目录的命令时,会尝试访问/proc/1/map_files——这个路径对应容器内PID 1进程的内存映射文件。但dind环境下的容器受Docker安全隔离机制限制,默认没有权限访问这类敏感的/proc子目录,尤其是在非特权模式运行时,就会触发Operation not permitted错误。
而本地MacOS的Docker Engine能正常运行,是因为MacOS的Docker实际跑在虚拟机上,虚拟机的权限模型和容器内的严格隔离不一样,对/proc目录的访问限制宽松很多,所以find /能顺利执行。
解决办法
这里有几个实用方案,你可以根据场景选择:
1. 缩小find的搜索范围(最推荐)
没必要遍历整个根目录,直接指定jar包所在的具体路径就行。比如你的jar包生成在/target或/app目录下,把命令改成:
RUN find /target -name "spring-cloud-config-server*.jar" ! -name "*sources*" -exec cp -t /tmp {} + && mkdir /runtime && mv /tmp/spring-cloud-config*.jar /runtime/config-service.jar && rm -...
这样既避开了/proc这类敏感目录,还能加快构建速度。
2. 在find中排除/proc目录
如果必须遍历大部分目录,可在命令里添加排除规则跳过/proc:
RUN find / -path /proc -prune -o -name "spring-cloud-config-server*.jar" ! -name "*sources*" -exec cp -t /tmp {} + && mkdir /runtime && mv /tmp/spring-cloud-config*.jar /runtime/config-service.jar && rm -...
-path /proc -prune会让find直接跳过/proc目录,自然不会触发权限问题。
3. 以特权模式运行Jenkins dind容器(谨慎使用)
如果上面的方法都不适用,可以尝试给Jenkins的dind容器添加特权权限。启动容器时加上--privileged参数:
docker run --privileged ... jenkins/jenkins:lts-dind
但要注意,特权模式会让容器获得主机几乎所有权限,安全性大幅降低,只有在完全信任运行环境的情况下才建议用。
4. 添加特定Linux能力(比特权模式更精细)
不想用完全特权的话,可以给容器添加SYS_PTRACE能力,这个权限允许进程访问/proc/[pid]/map_files这类路径:
docker run --cap-add SYS_PTRACE ... jenkins/jenkins:lts-dind
这种方式比特权模式更安全,但还是要评估风险后再使用。
内容的提问来源于stack exchange,提问作者Marcello DeSales

