LoginSignup
11
6

More than 3 years have passed since last update.

nginxとphp-fpmの通信設定について

Last updated at Posted at 2021-03-12

はじめに

この記事はプログラミング初学者による備忘録用の記事であり、少しでも他の初学者のお役に立てればと思い書いています。

今回はDockerでのnginxコンテナとphp-fpm(php)コンテナの通信設定(unixドメインソケット)に関することを調べてみました。

間違いなどがございましたら、ご指摘のほどよろしくお願い致します。

nginxとphp-fpm間のイメージ図

まずはざっくりと全体のイメージ図で繋がりを見てみます。
スクリーンショット 2021-03-12 10.35.09(2).png

このようなイメージになるかと思います。(間違っていればご指摘ください)

通信設定の流れ(ざっくりと説明)

大まかな流れ

1.docker-compose.ymlで名前付きボリュームをマウントする。
unixドメインソケット(php-fpm-socket)のボリュームは app コンテナと web コンテナで共用したいのでマウントします。

2.php-fpm側でphp-fpm.d/zzz-www.conf、nginx側でnginx/default.confnginx/nginx.confを使い設定を行います。

接続方法
TCPかUNIXドメインソケットのどちらかを選択して接続します。

UNIXドメインソケットは、TCPソケット(INETドメインソケット)よりもスループットが優れてるらしい。
下記の記事は参考になります。是非、読んでみてください。

順を追って、もう少し詳しく説明したいと思います。

docker-compose.ymlでの設定

docker-compose.yml
version: "3.8"

volumes:
  php-fpm-socket: #unixドメインソケットを使う為に名前付きボリュームを設定
  db-store:

services:
  # php
  app:
    container_name: php
    build: ./infra/docker/php
    volumes:
      - php-fpm-socket:/var/run/php-fpm 
#unixドメインソケット(php-fpm-socket)のボリュームはwebコンテナと共用するのでマウントする
      - ./backend:/work/backend

  # nginx
  web:
    container_name: nginx
    build: ./infra/docker/nginx
    ports:
      - 80:80
    volumes:
      - php-fpm-socket:/var/run/php-fpm
#unixドメインソケット(php-fpm-socket)のボリュームはappコンテナと共用するのでマウントする
      - ./backend:/work/backend
      #略

後ほど、/var/run/php-fpmphp-fpm.d/zzz-www.confnginx/default.confで使うことになります。

Dockerfile(php)

#略
RUN mkdir /var/run/php-fpm && \ 
#略
COPY ./php-fpm.d/zzz-www.conf /usr/local/etc/php-fpm.d/zzz-www.conf

COPY命令のディレクトリは構造により異なります。
コンテナ内のファイルシステム上を指すパスは一定です。

Dockerfile(nginx)

#略
# nginx config file
COPY ./default.conf /etc/nginx/conf.d/default.conf
COPY ./nginx.conf:/etc/nginx/nginx.conf
#略

COPY命令のディレクトリは構造により異なります。
コンテナ内のファイルシステム上を指すパスは一定です。

接続の設定(nginx)

nginxでは、nginx/default.confnginx/nginx.confを使い設定を行います。

nginx/nginx.confは、php-fpmとunixドメインソケットで通信するために、初期状態から実行ユーザをwww-dataに変更するために用意します。
nginx/default.confはdefault.conf内でphp-fpm.sockのpathを指定する為に用意します。pathを指定することでphp-fpmとの通信が成立します。

nginx/nginx.conf
# user  nginx;
user  www-data; #デフォルトからこの箇所のみ変更
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}
#略

nginx/nginx.confでは、php-fpmとunixドメインソケットで通信するために、初期状態から実行ユーザをwww-dataを追記します。

変更する理由
nginx+php-fpm環境でphpの処理にUNIXドメインソケットを使っている場合、DebianでPHPをアップグレードすると、「502 Bad Gateway」となって502エラーでハマるのを防ぐ為です。
詳しくは下記リンク先をお読みください。
https://setting-tool.net/nginx-php-fpm-socket-permission

nginx/default.conf
#略
location ~ \.php$ {
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        #/var/run/php-fpm/ に php-fpm.sock が作られてphpコンテナと通信が成立
    }

unixドメインソケットで接続する場合

nginx/default.confで、fastcgi_pass unix: /var/run/php-fpm/php-fpm.sock;
とpathを指定します。php-fpm.d/zzz-www.confと同じpath指定することで、nginxとphp-fpmでunixドメインメソットを使い通信できるようになります。

接続の設定(php-fpm)

php-fpmでは、php-fpm.d/zzz-www.confを使い設定を行います。

php-fpm.d/zzz-www.confは、php-fpm.sockのpathを指定する為と、実行ユーザーをnginx側の実行ユーザーと一致させる為に用意します。

php-fpm.d/zzz-www.conf
listen = /var/run/php-fpm/php-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0666

listen
FastCGIリクエストを受け入れるアドレスを設定、nginxと通信(接続)するためのUNIXドメインソケットのpathを指定します。fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;と同じpathを指定をすることで通信できるようになります。このオプションは、必須であり、 'ip.add.re.ss:port', 'port', '/path/to/unix/socket' 形式の構文が使えます。 

参考:php manual | php-fpm.conf のグローバル設定項目

listen.owner = www-data
unix ソケットを使う場合に、そのパーミッションを設定します。 読み書きアクセス権限(ユーザー)をnginxの実行ユーザーと同一設定しないとウェブサーバーからの接続を受け付けることができません。

listen.group = www-data
同様にnginxの実行ユーザーと統一させる。

注意
listen.ownerとlisten.groupで、nginxの実行ユーザーと別のユーザーを指定した場合

listen.owner = nginx
listen.group = nginx
下記のように、存在していないユーザーが設置されてますよとエラーがでます。

$ docker-compose logs

php    | [12-Mar-2021 11:57:31] ERROR: [pool www] cannot get uid for user 'nginx': Success (0)
php    | [12-Mar-2021 11:57:31] ERROR: [pool www] cannot get uid for user 'nginx': Success (0)
php    | [12-Mar-2021 11:57:31] ERROR: FPM initialization failed
php    | [12-Mar-2021 11:57:31] ERROR: FPM initialization failed

listen.mode = 0666
これがないとphp側でエラーが出ます。

$ docker-compose logs

php    | [14-Mar-2021 09:54:34] ERROR: [/usr/local/etc/php-fpm.d/zzz-www.conf:5] unknown entry '# listen.mode'
php    | [14-Mar-2021 09:54:34] ERROR: Unable to include /usr/local/etc/php-fpm.d/zzz-www.conf from /usr/local/etc/php-fpm.conf at line 5
php    | [14-Mar-2021 09:54:34] ERROR: failed to load configuration file '/usr/local/etc/php-fpm.conf'
php    | [14-Mar-2021 09:54:34] ERROR: FPM initialization failed

パーミッションの設定
WEBサイトなどを見ているユーザは、第三者です。
WEBページとして公開するHTML文書などは、「読み取り」 を許可する必要がありますが、CGIのファイルなど直接呼び出されるプログラムには、「書き込み」を許可しなければならない場合があります。
従って、各ユーザーにどこまで権限を与えるのかを考え、パーミッションを変更する必要があります。

今回のように0666とする場合、
用途としてはデータ記録など読み書き可能なファイルで、具体例として掲示板のようなものが該当します。

パーミッションに関することは下記記事が分かりやすかったです。

zzz-www.confというファイル名の理由
これは 公式イメージがzz-docker.confでlisten設定を破棄していることに対抗するためらしいです。後に読ませることでlisten設定が残るので、辞書順で後ろに来るようにzzz-www.confというファイル名にするらしいです。

詳しくは下記記事を読んでみてください。

fpm の設定ファイルをzzz-www.confとしていますが、これは 公式イメージが zz-docker.conf で listen 設定をぶっ潰しているのに対抗するためです。
後に読まれたものが勝つので。どう見ても暫定回避のような構造ですが仕方ありません。

おわりに

次はTCPやUNIXドメインソケットについて、もう少し詳しく学習してみようかなと思います。

最後まで読んでくださり誠にありがとうございました。

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6