カテゴリー
Linux

Nginx + PHP-FPM で unix ドメインソケットを使ったシンプルな docker-compose.yml を書きました。2

ポイント

  • 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.confuser nginx;user www-data; とし、
php:7.2-fpm の /usr/local/etc/php-fpm.d/zz-docker.conf に listen.owner = www-datalisten.group = www-data を追記すればよいです。

どちらのイメージにも、 www-data ユーザが最初から存在しますので、新たにユーザを作成する必要もありません。

では、この www-data ユーザとは一体何者なのか?

どうやら Debian 系における apache のデフォルト実行ユーザとのことです。

ですのでちょうどよいですね。

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 ドメインソケットについて、さらに整理と知識が付きました♪

次のページが参考になりました。ありがとうございます!

以上です。

コメントを残す