DEBUG.WIKI
丽萨主机;为跨境业务选好 IP;原生 / 住宅 IP · 按套餐选择;查看 IP →
阿里云;从建站到云上业务;云服务器 · 数据库 · 对象存储;查看产品 →
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Docker tmpfs 删了 noexec,仍报 Permission denied

删除tmpfs参数里的noexec仍可能保留Docker默认限制。核对Engine选项合并与实际挂载,按批准范围显式配置exec。

Docker 的 tmpfs 创建参数已经删掉 noexec,只保留 rw 等选项,运行文件却仍报 Permission denied。在实际挂载仍含 noexec 的情况下,要检查 Engine 合并默认选项的行为:删除用户参数中的限制,不等于覆盖了 Docker 先加入的默认限制。

这条处理路径针对临时文件确实位于 tmpfs,且普通用户权限、解释器与文件格式已核对的情况。文件根本不能创建时,先查非 root 进程与 tmpfs 目录属主,不要直接更改执行策略。

检查失败文件所在的挂载

先保存完整失败路径,再查看容器创建配置与运行时挂载。build-app 是示例容器名;容器包含 cat 时可只读检查:

docker inspect build-app --format '{{json .HostConfig.Tmpfs}}'
docker exec build-app cat /proc/mounts

采用 --mount type=tmpfs 等入口时,还需查看实际 Mounts 配置,不能因为 HostConfig.Tmpfs 为空就排除 tmpfs。运行时应找到真正覆盖失败路径的那条挂载;路径下有嵌套挂载时,不能只看 /tmp 上层。

挂载选项里明确出现 noexec,且失败文件的读取、执行位和路径访问条件均满足,才进入这条处理。若镜像已有 findmnt 等工具,也可用它确认目标路径的挂载与选项,无需给业务容器临时安装整套工具。

没有 noexec 时,继续查实际进程身份、文件模式、解释器或系统安全策略。不能仅凭同一条 Permission denied 就认定所有 tmpfs 都有这个问题。

rw 允许写入,不会撤销 noexec

Docker Engine 28.5.1 的 Linux tmpfs 挂载实现先加入 noexec、nosuid、nodev 等默认选项,再合并用户设置。因此,在这个实现中,从创建参数里删掉 noexec 不等于最终挂载变成可执行;仅声明 rw 也不改变执行限制。

应以运行容器的实际选项为准,其他版本与部署工具还需核对各自传参方式。不要把 exec=true 随意加到 --mount:该入口的参数结构与 --tmpfs 选项串不同。

给文件再次 chmod +x 也不会移除挂载的 noexec。直接执行受挂载策略阻止的文件,与文件本身没有执行位,是不同条件,需要分别核对。

确实需要执行时,给指定临时目录显式配置

先确认应用为什么要在该目录生成并执行文件,例如受控构建或运行时编译。如果部署策略本来要求临时目录禁止执行,应保留策略,改用经过批准的执行目录,而不是为通过一次构建放宽全部临时文件范围。

允许目标目录执行时,Docker CLI 的相关配置片段可以写为:

--tmpfs '/tmp:rw,exec,nosuid,nodev,size=512m'

这不是完整启动命令,应合并到服务原来的部署配置;512m 只是容量示例,需要符合应用用量和宿主资源预算。只在目标路径增加 exec,并保留其他所需限制。应用以非 root 用户运行时,目录属主、组与模式仍须独立配置,exec 不会自动授予写权限。

保存原参数,在隔离环境确认部署工具能够传递这些选项,再按既有流程重建受影响的容器。不能靠 restart 期待新的创建参数进入旧容器,也不应为修改这个选项启用特权或在宿主机上随意 remount。

tmpfs 中的内容会随容器停止而丢失,重建前确认没有需要保存的上传文件或业务状态。若目录实际承担持久数据,先修正存储设计,不能只改一个挂载标志后继续运行。

验收原来的执行步骤

新容器启动后重新检查失败路径的实际挂载选项,用原应用身份执行原先失败的合法任务。需要同时确认临时文件创建、执行及后续业务步骤;命令不再报权限错误,并不能证明整个构建或服务已经成功。

原错误仍在时,保留完整的新错误、挂载和权限记录,不连续叠加 chmod、root 和特权选项。需要回退时恢复原部署参数并重建;旧 tmpfs 文件不会随参数回退恢复。