前一阵子在公司的内网机器上创建镜像,php 的项目镜像一直无法创建成功,总是卡在安装 php 扩展时的那一层命令,提示的是在对扩展进行编译时没有权限,错误就是下边图上的提示。
这个时候开启了漫长的排错过程。首先既然提示权限不足了,先切了 root 再说,换成 root 执行依然报这个问题,排除账号权限问题。
再对比其他镜像 nginx、redis、mysql 镜像能够正常创建,排除 docker 服务出现问题。这个时候已经陷入了僵局,明明本地能创建成功的,为什么换个机器不行了。
收拾下糟糕的心情,继续排错,既然我的本地能创建成功,首先能确定是 Dockerfile 文件是没有问题,配置也是正确的,那就看下内网的机器 Docker 的版本,果然版本存在差异,内网的为19,本地的是24版本,差比较多了,但是想着版本不对和权限有什么关系,果断跳过这个差异点。
再次回到错误的原点,既然是构建镜像时那一层的错误,那我先去掉那层扩展的构建试试,果然去掉后是正常的,这就更加诡异了,php 的扩展方式是按照官方镜像教程做的,没道理会报错,接着就想着容器既然已经创建了,就进入容器内执行安装扩展试试,该死的容器内执行命令还是提示无权限。
尝试问了同事、GPT都无解,已经逐渐红温走向了暴躁。
最后其实还有一张牌问 google,我描述了一下自己碰到的问题,在 github 上找到了答案,问题的根本还是 docker 的版本过低,至于解迷的过程如下:
我所使用的 Dockerfile 镜像构建中,php 的构建层为 FROM php:8.2.17-fpm-alpine3.18,问题就出在了 alpine3.18 这个 linux 镜像上,原来 alpine3.14 发布后更新了一个叫做 faccessat2 的系统调度,这个就是专门负责系统上的文件权限检测的,并且更新文档说明了低于 docker 20的版本会有问题,至此镜像无法构建的问题算是彻底破案了!
解决方法
1、升级 docker ,这个最是简单粗暴,但是如果是线上环境或是多人共享主机的情况下慎用
2、修改 docker 后台运行配置,强制指定文件权限检测不使用 faccessat2 的系统调度。首先下载 docker 的默认配置文件,是一个json文件 https://github.com/moby/moby/blob/master/profiles/seccomp/default.json,下载完成后修改第一行配置 defaultAction ,将 SCMP_ACT_ERRNO 改为 SCMP_ACT_TRACE,然后建议把文件放到 docker 配置目录下 /etc/docker,
配置文件准备好了,接下来 docker 需要先停止后台服务,在启动 docker 指定参数,其中参数中的文件路径为刚才配置文件的绝对路径
dockerd --seccomp-profile=/etc/docker/default.json &
3、在 docker run 时修改默认的配置,没试过,只能甩个官方的链接
https://docs.docker.com/engine/security/seccomp/