ポイント
- 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 ドメインソケットの基礎的な部分がわかる
以上です。
