それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

nginxで unix ドメイン socket をlisten してバックエンド専用に設定する。

nginx 使いまくり問題

docker やCDNとか使ってると、いくつのプロキシが挟まるんだよ。管理面倒くさいんだよ。って問題にぶち当たる。特にphp 関連。

browser → 企業・学校内プロキシ → CDN → docker ホスト nginx → dockerコンテナnginx → php-fpm

コレ全部が、SSLのデクリプトとエンクリプションや、TCPコネクションでsyn/ack してると思うとゾッとしない話ではない。そりゃhttp2でTCP節約が必要になるよねって感じる。

リバースプロキシから裏側はTCPを減らせるのでは。

docker ホスト nginx → dockerコンテナnginx → php-fpm

この部分がlocalhost:9000とかで待ち受けてるけど、全部unix ドメインソケットにしてしまえば、接続も管理も楽になるんじゃないかと。

nginx が unix sock で待ち受ける

ポートの管理とかTCPのコネクションが面倒くさいので、unix ソケットでnginx を動かしてみたらどうだろうか。 と思ったので試してみた。

nginx で設定してみる。

/etc/nginx/sites-enabled/default

server {
  #listen 80 default_server;
  #listen [::]:80 default_server;
  listen unix:/var/lib/nginx/backend.sock;
  access_log off;

  # SSL configuration
  #
  ##略
}

接続してみる

echo  'GET /' | nc -U /var/lib/nginx/backend.sock

nginx のunix:sock に応答する プロキシを 構成する。

リバースプロキシからバックエンドのnginxにunixソケットで接続できるようにする。

nginx:80 → nginx:sock に対応するものを作る。

upstream nginx-internal-sock {
    server unix:/usr/local/var/run/nginx-internal.sock;
}
server{

    listen 80;
    server_name 'www';
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Accept-Encoding "";
        proxy_pass http://nginx-internal-sock;
    }

}

または次のように書く

server{

  listen 80;
  server_name 'www';
  
  location / {
    proxy_pass http://unix:/usr/local/var/run/nginx-internal.sock; 
    ## ↑ http://unix:/ は記述ミスじゃなくて本当にこう書きます
  }

}

パスが違うのは、docker の起動時にボリュームでマッピングしてるから

-v /usr/local/var/run/:/var/lib/nginx/

socket ファイルを直接ボリュームマッピングすると socket がすでに存在しますと言われて起動できないので注意

何に使うの?

ポートの管理が面倒くさい。

docker で localhost:8001 / localhost:8002 / localhost:8003 と次々とnginxが占拠していくので何がなんだかわからなくなる。

とくに、nginx→(nginx+phpfpm) 間のリバースプロキシをすると管理が面倒くさいし、docker-composeのYAMLもだんだん増えてしまうので、ファイル名で扱うほうが楽かなかって思ったりしてる。ポート被らないし、ファイル名で識別できるし。ドメインソケットのほうがちょっとだけ速いし。

nginx-fpm をワンペアで扱う

apache+mod_php を使うのであれば、Apacheインスタンスを見ておけばいいが、 fastcgi+apachefastcgi+nginx にすると管理が面倒くさいのでソケットを volumeで外に出そうかなと。

アプリ側の設定 sites-enabled/myapp-php.nginx

upstream my-app-php-fpm {
   server unix:/usr/local/var/run/php-fpm/php-fpm.sock;
}
server{

    listen unix:/usr/local/var/run/my-app-nginx-internal.sock;
    root /var/www/html;

    location ~* \.php$ {
    fastcgi_pass  my-app-php-fpm;
    }

}

フロント側の設定。 sites-enabled/www.myapp.example.com.nginx

upstream nginx-internal-sock {
    server unix:/usr/local/var/run/my-app-nginx-internal.sock;
}
server{

    listen 80;
    server_name www.myapp.example.com;
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Accept-Encoding "";
        proxy_pass http://nginx-internal-sock;

    }

}

こうしておけば、unix socket でバックエンドにつながるので、マシン上に大量にのっけてもポート管理が煩雑にならない。

pull して実行したらcomposer.yaml でポート被った!あああぅっ。ってならなくて済むんじゃないかなと。