Node.jsをunix domain socketでlistenしたときにNginxからプロキシできない
という現象に対応した際のメモ。
環境
CentOS 7 on VirtualBoxです。
Nodeのソース
// express使っている var sockPath = '/tmp/node.sock'; var server = app.listen(sockPath, function() { console.log('Listening on port %d', server.address().port); });
nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
upstream app {
server unix:/tmp/node.sock;
}
server {
location / {
proxy_pass http://app;
}
}
}
現象
curl localhost
すると 502Bad Gatewayが返る。
nginxのerror.logには
2015/07/29 11:05:16 [crit] 10781#0: *1 connect() to unix:/tmp/node.sock failed (2: No such file or directory) while connecting to upstream, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://unix:/tmp/node.sock:/", host: "localhost"
とな。
対処方法
とりあえず、ググってみたところ、下記のページがひっかかりました。
/tmpをプロセス間のコミュニケーションに使ってはいかんと最近はなっているとのこと。
試しに、/tmp→/var/lib/appに変更してみました。
すると今度はPermission deniedと怒られました。
2015/07/29 11:26:03 [crit] 10995#0: *15 connect() to unix:/var/lib/app/node.sock failed (13: Permission denied) while connecting to upstream, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://unix:/var/lib/app/node.sock:/", host: "localhost"
更にググったところ
な回答があったので、
以下のコマンドでnginxをnode.jsのアプリのフォルダに触れるようにし、
chown nodeuser:nginx /var/lib/app chmod g+rxs /var/lib/app # これでnginxグループのrxがnode.sockにも継承される!
さらに、
var sockPath = '/var/lib/app/node.sock'; try { fs.unlinkSync(sockPath); } catch(e) { } var server = app.listen(sockPath, function(err) { if (err) throw err; fs.chmodSync(sockPath, '660'); console.log('Listening on port %d', server.address().port); });
な感じで、なんとか動くようにはなりました。
なお、node.sockにはnginxグループのwrite権限が必要なので、chmodSyncは必要です。
が、イマイチスマートでない。。納得いかない。。
※追記:こちらの方法でいけるかもしれない(試してはいない)