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 がまだ「ネイティブに」(docker 化されていない) 実行されており、そのソケットを nginx コンテナーに使用したいことです (そのため、行volumes: - "/run/php:/run/php")。

ソケットの権限は ですsrw-rw---- www-data:www-data。したがって、コンテナ ユーザーをグループ 33 (ホスト システム上の www-data -> group_add: ["33"]) に追加しました。コンテナでグループ ID を確認すると、ID は33現在ログインしているユーザーに追加されています。

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

それでも、PHP で動作する Web サイトを呼び出すと、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ユーザー として実行されます。

rootdocker-compose ファイル内のグループにユーザーを追加しましたがwww-data、これを行わなくても、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 workernginx

まず、docker コンテナ内のファイルの権限を確認しましょう...

ls -al次のような出力が得られます。

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

/etc/groupソケット ファイルは "xfs" によって所有されていることを示しています。コンテナー内のファイルをざっと見ると、グループの IDがホスト マシン上のグループの ID と同じでxfsあることがわかります。33www-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 ネットワーク スタックが提供されます。

権限の問題を修正したとしても、たとえば、ソケット ファイル 666 を使用してコンテナーに手動でログインしdocker execchmod簡潔にするためにユーザー名前空間も存在しないと仮定します。

あなたが求めているのは、次のことと同等です:

  1. Unixソケットでphp-fpmインスタンスを実行するsystem1/var/run/php-fpm.sock
  2. /var/run上の NFS 経由でパスをエクスポートしますsystem1
  3. system1:/var/runに取り付けますsystem2。完全に独立したシステムです。
  4. connect()前述の Unix ソケットをソケットオンにしようとしておりsystem2system1応答を期待していますphp-fpm

これを実際に行うべき方法(実際には欲しいこれを行うには、別の問題ですが、IP を使用してインスタンスをリッスンしphp-fpm、たとえば にバインドしますhost_system:12345。次に、nginxを使用してcontainerに接続しますhost_system:12345


これはすべて間違っています。私の言うことを聞かないでください。どちらかの名前空間で公開され、パスが両方の名前空間で共有されている、適切に名前付けされた UNIX ソケットを作成すると、その UNIX ソケットに接続すると、もう一方の名前空間に接続されます。

https://lore.kernel.org/all/[メールアドレス]/T/

このパッチは特にこれに対処します。明らかに、私がこれをテストしたのはかなり昔のことです! :)

これが当てはまらない唯一のケースは、匿名の Unix ソケットの作成の場合ですが、これは Linux に特有のものであり、Unix ソケットの機能としてはあまり使用されません。

関連情報