作为卷安装在 Docker 容器中的 Unix 套接字的权限被拒绝

作为卷安装在 Docker 容器中的 Unix 套接字的权限被拒绝

我尝试将当前在服务器上运行的 nginx 容器化。为此,我创建了以下 docker compose 文件:

version: "3.8"
services:
  nginx:
    image: nginx:stable-alpine
    container_name: nginx
    restart: unless-stopped
    group_add: ["33"]
    volumes:
      - "/etc/nginx-docker:/etc/nginx/conf.d:ro"
      - "/run/php:/run/php"
      - "/var/www:/var/www:ro"
    ports:
      - "8111:80"
      - "8443:443"

一切工作正常,但问题是,我的主机系统上仍然有 php-fpm“本地”运行(未 dockerized),并且我想将它们的套接字用于我的 nginx 容器(因此有此行volumes: - "/run/php:/run/php")。

套接字的权限是srw-rw---- www-data:www-data。因此,我将容器用户添加到组 33(即我的主机系统上的 www-data -> group_add: ["33"])。当我在容器中检查组 ID 时,该 ID33确实已添加到当前登录的用户:

/ # id -G
0 1 2 3 4 6 10 11 20 26 27 33
/ # id -u
0
/ # whoami
root

尽管如此,当我调用由 PHP 驱动的网站时,我在 nginx 日志中收到以下错误消息:

2024/01/21 08:58:53 [crit] 21#21: *1 connect() to unix:/run/php/php8.2-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.192.68, server: _, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.2-fpm.sock:", host: "op---s:8111"

有什么提示或解决方案可以使其工作吗?

答案1

我做了一些挖掘:)

如果你进入运行 nginx 镜像的容器,你会看到有几个 nginx 进程正在运行:

docker exec -it 43b5b971c433 /bin/sh

/ # ps -ef |grep nginx
    1 root      0:00 nginx: master process nginx -g daemon off;
   21 nginx     0:00 nginx: worker process
   22 nginx     0:00 nginx: worker process
   23 nginx     0:00 nginx: worker process
   24 nginx     0:00 nginx: worker process
   42 root      0:00 grep nginx

有些以 身份运行root,有些以nginx用户身份运行。

您已将用户添加rootwww-datadocker-compose 文件中的组中,但即使不这样做,root 用户也应该拥有访问 php unix 套接字所需的所有权限。

您可以使用以下test命令测试权限。输出退出代码以查看命令是否成功。如您所见,root 用户可以读取套接字文件,但不能执行它:

/run/php # whoami
root
/run/php # test -r  php8.1-fpm.sock; echo $?
0
/run/php # test -x  php8.1-fpm.sock; echo $?
1

因此permission denied错误可能来自nginx worker以用户身份运行的进程nginx

让我们首先检查 docker 容器内文件的权限...

ls -al输出结果如下:

srw-rw----    1 xfs      xfs              0 Jan 25 08:58 php8.1-fpm.sock

表示套接字文件归“xfs”所有。快速查看/etc/group容器内的文件会发现xfs组的 ID33与主机上组的 ID 相同www-data

在容器内部,可以将 nginx 用户添加到 xfs 组:

addgroup nginx xfs

现在该问题应该已经解决了。

我不确定如何将其直接添加到您的撰写文件中(您如何指定要添加到组中的用户?) - 但如果您可以创建一个新的图像,您可以在您的 Dockerfile 中执行此操作。

但重新启动容器后,权限似乎仍然存在。

答案2

确定 PHP-FPM 在主机上运行的用户和组。您通常可以在 PHP-FPM 配置文件中找到此信息(通常位于 /etc/php/7.x/fpm/pool.d/www.conf)

然后更新你的docker-compose并添加这个

user: "your_php_user:your_php_group"

答案3

一切工作正常,但问题是,我的主机系统上仍然有 php-fpm“本地”运行(未 dockerized),并且我想将它们的套接字用于我的 nginx 容器(因此有行 volumes: - "/run/php:/run/php")。

这是不可能的,也是没有意义的。

Docker 生成了自己的网络命名空间,因此您可以获得自己的防火墙堆栈、IP 堆栈和 Unix 网络堆栈。

即使您解决了权限问题,假设您使用套接字文件 666 手动登录到容器,docker exec并且chmod为了简洁起见,我们假设其中没有用户命名空间。

您要求执行的操作相当于:

  1. 使用 Unix 套接字运行php-fpm实例system1/var/run/php-fpm.sock
  2. /var/run通过 NFS导出路径system1
  3. 安装system1:/var/run在 上system2。一个完全独立的系统。
  4. 尝试connect()对所述 Unix 套接字套接字进行连接system2并期望system1用 进行响应php-fpm

你实际上应该这样做(实际上应该要做到这一点(这是另一回事),需要php-fpm使用 IP 监听实例 -- 将其绑定到host_system:12345例如。然后使用nginxincontainer连接到host_system:12345


这完全是错误的。别听我的。如果你创建一个命名良好的 unix 套接字,在任一命名空间中公开,并且路径在两个命名空间之间共享,则连接到该 unix 套接字将连接到另一个命名空间!

https://lore.kernel.org/all/[电子邮件保护]/T/

此补丁专门解决了这个问题。显然,当我测试它时已经是很久很久以前的事情了!:)

唯一一次出现这种情况的情况是在匿名 Unix 套接字创建案例中,然而这是一个 Linux 特有的并且不常用的 Unix 套接字功能。

相关内容