Отказано в доступе для сокета unix, смонтированного в контейнере docker как том

Отказано в доступе для сокета unix, смонтированного в контейнере docker как том

Я пытаюсь контейнеризировать мой 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 «в исходном виде» (не в Docker), и я хочу использовать их сокеты для своего контейнера nginx (отсюда и строка volumes: - "/run/php:/run/php").

Разрешения сокетов равны srw-rw---- www-data:www-data. Поэтому я добавил пользователя контейнера в группу 33 (которая является www-data на моей хост-системе -> group_add: ["33"]). Когда я проверяю идентификаторы групп в контейнере, идентификатор 33действительно добавляется к текущему вошедшему в систему пользователю:

/ # 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пользователя.

Вы добавили пользователя rootв www-dataгруппу внутри файла docker-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- 33такой же, как идентификатор на хост-машине для группы www-data.

Внутри контейнера вы можете добавить пользователя nginx в группу xfs:

addgroup nginx xfs

Проблема должна быть устранена сейчас.

Я не уверен, как добавить это непосредственно в ваш файл Compose (как указать, какого пользователя добавить в группу?), но вы можете сделать это в своем 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 «в исходном виде» (не в Docker), и я хочу использовать их сокеты для своего контейнера nginx (отсюда и строка volumes: - "/run/php:/run/php").

Это невозможно и неразумно.

Docker создает собственное сетевое пространство имен, поэтому вы получаете собственный стек брандмауэра, стек IP и сетевой стек Unix.

Даже если вы исправите проблему с разрешениями, предположим, что вы входите в контейнер вручную с помощью docker execфайла chmodсокета 666, и для краткости предположим, что на пути нет никаких пространств имен пользователей.

То, что вы просите сделать, эквивалентно следующему:

  1. Запуск php-fpmэкземпляра system1с сокетом Unix/var/run/php-fpm.sock
  2. Экспорт /var/runпути по NFS на system1.
  3. Монтаж system1:/var/runна system2. Полностью отдельная система.
  4. Попытка connect()подключиться к сокету Unix system2и ожидание system1ответа php-fpm.

То, как вы на самом деле должны это сделать (на самом деле должныхотетьдля этого (что является отдельным вопросом) нужно прослушивать экземпляр с использованием IP -- например, php-fpmпривязывая его к . Затем использовать in для подключения к .host_system:12345nginxcontainerhost_system:12345


Это все просто неправильно. Не слушайте меня. Если вы создаете правильно названный сокет unix, открытый в любом из пространств имен, и путь является общим для обоих пространств имен, подключение к этому сокету unix подключается к другому пространству имен!

https://lore.kernel.org/all/[email protected]/Т/

Этот патч как раз решает эту проблему. Очевидно, когда я это тестировал, это было очень давно! :)

Единственный случай, когда это не так, — это случай создания анонимного сокета Unix, однако это довольно специфичная для Linux и нечасто используемая функция сокетов Unix.

Связанный контент