ポイント
- Docker イメージは、 alpine を使わない。
- Nginx の実行ユーザと PHP-FPM の listen.owner 、 listen.group とを一致させる。
- Nginx で fastcgi_pass に指定するファイルのディレクトリと、 PHP-FPM で listen に指定するファイルのディレクトリとを、 Docker Compose のトップレベルで定義する名前付き volume で共有する。
ソースコード
ポイントの解説
Docker イメージは、 alpine を使わない。
軽量化しようと思いましたが、次のようにしては動きませんでした><。
両方 alpine にすると動かないのではなく、どちらか一方だけでも alpine とすると動きませんでした。
version: '3' volumes: php_sockert: services: nginx: image: nginx:alpine ports: - 80:80 volumes: - ./volumes/html:/usr/share/nginx/html - ./volumes/nginx/nginx/nginx.conf:/etc/nginx/nginx.conf - ./volumes/nginx/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf - php_sockert:/var/run depends_on: - php_fpm php_fpm: image: php:7.2-fpm-alpine volumes: - ./volumes/html:/usr/share/nginx/html - ./volumes/php_fpm/php-fpm.d/zz-docker.conf:/usr/local/etc/php-fpm.d/zz-docker.conf - php_sockert:/var/run
nginx:alpine とした場合
この Docker イメージでは、 www-data ユーザが作成されません。
一方、 nginx.conf で user に www-data を指定します。
存在しないユーザを指定して Nginx を起動しようとするため、エラーとなり、コンテナ自体が立ち上がりませんでした。
$ # コンテナを起動 $ docker-compose up -d Creating samplenginxphpfpm_php_fpm_1 ... done Creating samplenginxphpfpm_nginx_1 ... done $ # コンテナの稼働状況を確認すると、 Nginx が停止している。 $ docker-compose ps Name Command State Ports ------------------------------------------------------------------------------- samplenginxphpfpm_nginx_1 nginx -g daemon off; Exit 1 samplenginxphpfpm_php_fpm_1 docker-php-entrypoint php-fpm Up 9000/tcp $ $ # ログを確認すると、設定ファイルが原因で Nginx が立ち上がっていない。 $ docker-compose logs Attaching to samplenginxphpfpm_nginx_1, samplenginxphpfpm_php_fpm_1 nginx_1 | 2018/11/13 22:31:36 [emerg] 1#1: getpwnam("www-data") failed in /etc/nginx/nginx.conf:2 nginx_1 | nginx: [emerg] getpwnam("www-data") failed in /etc/nginx/nginx.conf:2 php_fpm_1 | [13-Nov-2018 22:31:36] NOTICE: fpm is running, pid 1 php_fpm_1 | [13-Nov-2018 22:31:36] NOTICE: ready to handle connections $ $ $ $ # nginx:alpine コンテナを別途起動し、入る。 $ docker run --rm -it --name na nginx:alpine sh / # / # # www-data ユーザの存在を確認すると、存在しない。 / # cat /etc/passwd root:x:0:0:root:/root:/bin/ash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin news:x:9:13:news:/usr/lib/news:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin operator:x:11:0:operator:/root:/bin/sh man:x:13:15:man:/usr/man:/sbin/nologin postmaster:x:14:12:postmaster:/var/spool/mail:/sbin/nologin cron:x:16:16:cron:/var/spool/cron:/sbin/nologin ftp:x:21:21::/var/lib/ftp:/sbin/nologin sshd:x:22:22:sshd:/dev/null:/sbin/nologin at:x:25:25:at:/var/spool/cron/atjobs:/sbin/nologin squid:x:31:31:Squid:/var/cache/squid:/sbin/nologin xfs:x:33:33:X Font Server:/etc/X11/fs:/sbin/nologin games:x:35:35:games:/usr/games:/sbin/nologin postgres:x:70:70::/var/lib/postgresql:/bin/sh cyrus:x:85:12::/usr/cyrus:/sbin/nologin vpopmail:x:89:89::/var/vpopmail:/sbin/nologin ntp:x:123:123:NTP:/var/empty:/sbin/nologin smmsp:x:209:209:smmsp:/var/spool/mqueue:/sbin/nologin guest:x:405:100:guest:/dev/null:/sbin/nologin nobody:x:65534:65534:nobody:/:/sbin/nologin nginx:x:100:101:Linux User,,,:/var/cache/nginx:/sbin/nologin / # $
php:7.2-fpm-alpine とした場合
Nginx は alpine としないで、PHP のみ alpine としました。
すると、Nginx から見た /var/run/php7-fpm.sock
のユーザとグループが 82 となっていました。
Nginx は www-data であることを期待しており、 82 と合わないのために、パーミッションエラーとなりました。
$ # ログを確認 $ docker-compose logs -f ... 略 ... nginx_1 | 2018/11/13 22:37:02 [crit] 7#7: *2 connect() to unix:/var/run/php7-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 172.24.0.1, server: localhost, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php7-fpm.sock:", host: "localhost" nginx_1 | 172.24.0.1 - - [13/Nov/2018:22:37:02 +0000] "GET /index.php HTTP/1.1" 404 555 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36" "-" nginx_1 | 2018/11/13 22:37:02 [error] 7#7: *2 open() "/usr/share/nginx/html/50x.html" failed (2: No such file or directory), client: 172.24.0.1, server: localhost, request: "GET /index.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/php7-fpm.sock", host: "localhost" ... 略 ... $ $ # PHP-FPM コンテナに入って確認すると、 /var/run/php7-fpm.sock のユーザとグループは www-data となっており、想定通り。 $ docker-compose exec php_fpm sh /var/www/html # ls -al /var/run/ total 12 drwxr-xr-x 2 root root 4096 Nov 13 22:35 . drwxr-xr-x 1 root root 4096 Nov 13 22:35 .. -rw-r--r-- 1 root root 2 Nov 13 22:35 nginx.pid srw-rw---- 1 www-data www-data 0 Nov 13 22:35 php7-fpm.sock $ $ # Nginx コンテナに入って確認すると、 /var/run/php7-fpm.sock のユーザとグループが 82 となっており、これが原因。 $ docker-compose exec nginx bash root@471a6f73b9f9:/# ls -al /var/run/ total 12 drwxr-xr-x 2 root root 4096 Nov 13 22:35 . drwxr-xr-x 1 root root 4096 Nov 13 22:35 .. -rw-r--r-- 1 root root 2 Nov 13 22:35 nginx.pid srw-rw---- 1 82 82 0 Nov 13 22:35 php7-fpm.sock root@471a6f73b9f9:/# exit $
Nginx の実行ユーザと PHP-FPM の listen.owner 、 listen.group とを一致させる。
具体的には、 nginx:latest の /etc/nginx/nginx.conf
の user nginx;
を user www-data;
とし、
php:7.2-fpm の /usr/local/etc/php-fpm.d/zz-docker.conf に listen.owner = www-data
と listen.group = www-data
を追記すればよいです。
どちらのイメージにも、 www-data ユーザが最初から存在しますので、新たにユーザを作成する必要もありません。
では、この www-data ユーザとは一体何者なのか?
どうやら Debian 系における apache のデフォルト実行ユーザとのことです。
- apache のデフォルト実行ユーザ www-data で github や bitbucket にSSH 接続する – Qiita
- www-dataイズ誰? – このひとときに……魂を込めて……!@アイカツスターズ!を見てください
ですのでちょうどよいですね。
Nginx で fastcgi_pass に指定するファイルのディレクトリと、 PHP-FPM で listen に指定するファイルのディレクトリとを、 Docker Compose のトップレベルで定義する名前付き volume で共有する。
次のようにすることで、Nginx コンテナからも、 PHP-FPM コンテナからも、同じ /var/run/php7-fpm.sock
を利用できるようになります。
UNIX ドメインソケットはもともとは自マシン内でのみ使うもののようです。
ですのでコンテナ同士の通信に使うと性能が劣化しているかも知れません。そこは検証しておりません。
version: '3' volumes: php_sockert: services: nginx: image: nginx:latest ports: - 80:80 volumes: - ./volumes/html:/usr/share/nginx/html - ./volumes/nginx/nginx/nginx.conf:/etc/nginx/nginx.conf - ./volumes/nginx/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf - php_sockert:/var/run depends_on: - php_fpm php_fpm: image: php:7.2-fpm volumes: - ./volumes/html:/usr/share/nginx/html - ./volumes/php_fpm/php-fpm.d/zz-docker.conf:/usr/local/etc/php-fpm.d/zz-docker.conf - php_sockert:/var/run
Nginx では、あくまで Nginx が Nginx コンテナ (自分自身) の /var/run/php7-fpm.sock
を見に行くと理解しています。
server { listen 80; server_name localhost; #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 location ~ \.php$ { root /usr/share/nginx/html; fastcgi_pass unix:/var/run/php7-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} }
そして、PHP-FPM コンテナでは、自分自身のコンテナ内にある、 /var/run/php7-fpm.sock
を利用しているはずです。
[global] daemonize = no [www] listen = /var/run/php7-fpm.sock listen.owner = www-data listen.group = www-data
おわりに
本投稿は、Nginx + PHP-FPM で unix ドメインソケットを使ったシンプルな docker-compose.yml を書きました。 – oki2a24 の進化版となります。
Nginx について、 UNIX ドメインソケットについて、さらに整理と知識が付きました♪
次のページが参考になりました。ありがとうございます!
- Concrete5 on Nginx + php7-fpm を docker-compose でやってみた – Qiita
本投稿のような具体的な実践例 - Nginx+PHP-FPMでUNIXドメインソケットを使っていてハマる | 設定やツールねた
sock ファイルへのアクセス問題を解決するページ - nginx と PHP-FPM の仕組みをちゃんと理解しながら PHP の実行環境を構築する – Qiita
実践例を交えつつ、 TCP と UNIX ドメインソケットの違いを解説 - 調べなきゃ寝れない!と調べたら余計に寝れなくなったソケットの話 – Qiita
UNIX ドメインソケットの基礎的な部分がわかる
以上です。