php-fpm on Docker

【[当研究室のシステム](https://qiita.com/NeK/items/70f994b271b0c1a48590)】
# 概要

後々apache2と組み合わせるが，ここではphp-fpmのみを考える．
[php - Official Image](https://hub.docker.com/_/php)を利用するが，phpモジュールをインストールするので`docker pull`でそのままイメージを利用するのではなくベースイメージ(DockerfileのFROM)として用いる．

## 前提

* 使用イメージ
    * php:8.2.5-fpm-bullseye
        * alpineは(特にdnsのsearchが効かないところで)ハマったのでbullseyeを利用
* phpモジュールのインストール
    * [install-php-extensions](https://github.com/mlocati/docker-php-extension-installer)を利用
* apache2とのやり取り
    * unix socketを想定
        * /var/run/php-fpm/php-fpm.sock経由
* 作業ディレクトリ
    * ~/Docker/php-fpm/
        * Dockerfile, docker-compose.yml置き場

# 設定
以下のDockerfile, docker-compose.ymlを準備．
phpモジュールとしてcurlを書いてあるが，これはデフォルトで入っている．よって書かなくて良い．ここでは「ここにモジュール名を羅列する」ことを明記するために書いてある．他のphpモジュールをインストールする場合，curlの後ろにスペース区切りで追記することになる．

```Dockerfile:~/Docker/php-fpm/Dockerfile
FROM php:8.1.18-fpm-bullseye

RUN set -x && \
    curl -sSLf \
        -o /usr/local/bin/install-php-extensions \
        https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions && \
    chmod +x /usr/local/bin/install-php-extensions && \
    install-php-extensions curl

ENV TZ=Asia/Tokyo

# Use the default production configuration
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" && \
    sed -i 's/memory_limit = 128M/memory_limit = -1/' "$PHP_INI_DIR/php.ini" && \
    sed -i 's/post_max_size = 8M/post_max_size = 20480M/' "$PHP_INI_DIR/php.ini" && \
    sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 20480M/' "$PHP_INI_DIR/php.ini" && \
    sed -i 's/max_execution_time = 30/max_execution_time = 600/' "$PHP_INI_DIR/php.ini" && \
    sed -i 's/;max_input_vars = 1000/max_input_vars = 5000/' "$PHP_INI_DIR/php.ini" && \
    cp /usr/local/etc/php-fpm.d/www.conf /usr/local/etc/php-fpm.d/zzz-www.conf && \
    sed -i 's!pm.max_children = 5!pm.max_children = 10!' /usr/local/etc/php-fpm.d/zzz-www.conf && \
    sed -i 's!listen = 127.0.0.1:9000!listen = /var/run/php-fpm/php-fpm.sock!' /usr/local/etc/php-fpm.d/zzz-www.conf && \
    sed -i 's!;listen.owner = www-data!listen.owner = www-data!' /usr/local/etc/php-fpm.d/zzz-www.conf && \
    sed -i 's!;listen.mode = 0660!listen.mode = 0660!' /usr/local/etc/php-fpm.d/zzz-www.conf
```

```yml:~/Docker/php-fpm/docker-compose.yml
version: '3.9'
    
services:
  php-fpm:
    build: . 
    image: nek/php-fpm:latest
    container_name: php-fpm
    hostname: php-fpm
    restart: always
    volumes:
      - socket:/var/run/php-fpm
      - /etc/group:/etc/group:ro
      - /etc/passwd:/etc/passwd:ro
```

## ハマりポイント
### php-fpm.d/*.conf
php-fpmでは<font color=red>最後に読み込んだconfのみ有効になる</font>上，`zz-docker.conf`が存在する．そのため`www.conf`をいじっても有効にならない．
そこで`www.conf`を`zzz-www.conf`としてコピーし，最後に読み込まれる(同ディレクトリ内にてアルファベット順で最後になる)ようにして設定を書き込む．

### user, groupについて
連携させるapache2とphp-fpmでwww-dataのuid,gidが異なる．例えばapache2ではwww-data(33)であるがphp-fpmではwww(82)である．
そのためホストの`/etc/group`と`/etc/passwd`をマウントし，uid, gidを合わせている．apache2, nginxのオフィシャルイメージを使えば問題なかったのだろうが．．．

### ハマるほどではないけれど？
8.2系から少し変わったようで，nextcloudで`Using ${var} in strings is deprecated,...`というエラーがでる．
いやなので8.1.18を使用する．

# 運用
## 起動

```bash
cd ~/Docker/php-fpm
docker compose up -d
```

## 起動確認
php-fpm.sockの作成まで出来ているか確認．

```bash
docker container exec -it php-fpm bash
cd /var/run/php-fpm
ls # php-fpm.sockが見えている？ 
```

# 参考
* [【PHP-FPM】適切なプロセス設定について](https://thoames.hatenadiary.jp/entry/2020/05/12/073656)
* [php-fpm の設定を理解してサイトのパフォーマンスを向上させる](https://hackers-high.com/linux/php-fpm-config/#php-fpm-3)