
Heroku上にオリジナルのアプリケーションを構築したとして、それを公開するにはリバースプロキシを経由するのが一般的です。今回はHeroku上に作った自分のアプリケーションへのリバースプロキシをNginxで構築する方法を紹介します。
見出し
リバースプロキシ(Reverse proxy)とは
リバースプロキシとは、簡単に言ってしまえばエンドユーザとアプリケーション(バックエンド)の間を仲介するサーバーの事です。なぜそんなサーバが必要なのかと言えば、ロードバランサーとして利用することで負荷分散(バックエンドのスケールアウト)を可能にしたり、冗長化されたノードの一つに問題が発生した時にうまく他のノードに割り振ったり(可用性)、メンテナンスの時にバックエンドへのアクセスを止めたり、キャッシュしたり(性能)、SSL対応を共通化したり、といった事を実現するためです。
少々小難しい表現なので、少し違った視点で例えると、
Webデザイナーにとってのワイヤーフレームに少し似ています。(アイデアとHTMLの間)
アプリケーションエンジニアにとってのインターフェースに対する設計に少し似ています。(定義と実装の間)
お客さんとエンジニアの間にいる交渉役のリーダーやシニアエンジニアに似ています。(お客さんとエンジニアの間)
平社員の愚痴を聞き、部長の意向を聞く、中間管理職に似ています。(平社員と部長の間)
どれも間に無いと困りますね。いつもお疲れ様です。逆に混乱した人はWikipediaのリバースプロキシの説明を見てください。それよりは分かり安く説明したつもりですが。
ということで、今回はすでにHeroku上にオリジナルのアプリケーションを構築済みである前提で、さらにNginxを使ったリバースプロキシをHeroku上に構築する方法を紹介します。
Heroku上で動くNginxのリバースプロキシの設定
事前にDockerコマンドとHerokuコマンドは使えるように準備しておいて下さい。
それでは、やっていきましょう!
必要なフォルダとファイルを作る
今回用のプロジェクトを作りましょう。
$ mkdir herokuapp-proxy
$ cd herokuapp-proxy
$ touch nginx.conf.erb
$ touch boot.sh
$ touch Dockerfile
$ touch docker-compose.yml
この時点で全体像が見えますね。
nginx.conf.erbを作る
通常Nginxの設定ファイルはnginx.confですが、RubyのERBファイルにします。理由は、Herokuがポートを自動で割り振る仕様になっているため、コンテナ起動時にHerokuの環境変数PORTを参照して設定する必要があるためです。ついでにHerokuに設定した自分の環境変数も参照できるので便利です。
daemon off;
worker_processes <%= ENV['NGINX_WORKERS'] || 4 %>;
http {
upstream heroku_app {
server {your-webapp-yyyyy}.herokuapp.com;
}
server{
listen <%= ENV["PORT"] %>;
server_name _;
location ^~ / {
proxy_pass http://heroku_app;
proxy_redirect off;
proxy_set_header Host {your-webapp-yyyyy}.herokuapp.com;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Server $http_host;
proxy_set_header Connection '';
proxy_http_version 1.1;
}
}
}
{your-webapp-yyyyy}のところは、プロキシを接続するHerokuアプリのドメインに置き換えて下さい。
boot.shを作る
次にコンテナ実行時のコマンドをシェルスクリプトにします。
#!/bin/sh
# build
/usr/bin/erb /usr/local/openresty/nginx/conf/nginx.conf.erb > /usr/local/openresty/nginx/conf/nginx.conf
# start nginx
/usr/local/openresty/nginx/sbin/nginx
単にERBファイルをビルドして、Nginxを起動しているだけです。
Dockerfileを作る
続いてNginxのDockerファイルを作ります。今回はopenrestyのイメージを使います。これを使うとLuaが最初から使えるので便利です。ただ、今回はLuaは使わないので、普通のNginxの公式イメージでも問題ありません。
FROM openresty/openresty:1.13.6.1-1-alpine
ENV PATH $PATH:/usr/sbin/
COPY nginx.conf.erb /usr/local/openresty/nginx/conf/nginx.conf.erb
COPY boot.sh /boot.sh
RUN chmod +x /boot.sh
RUN apk update \
&& apk add ruby
CMD ["/boot.sh"]
Herokuアプリとして登録する
herokuapp-proxyをHerokuに登録しましょう。
$ heroku container:login
$ heroku create
Creating app... done, ⬢ your-proxyapp-xxxxx
この時にnginx.conf.erbにオリジナルの環境変数(今回で言うところのNGINX_WORKERS)を書いている場合はheroku config:setコマンドで必要に応じて設定しましょう。
docker-compose.ymlを作る
HerokuのDockerレジストリにPushするために、Docker ComposeのYAMLを作りましょう。
version: '3'
services:
proxy:
image: registry.heroku.com/{your-herokuapp-xxxxx}/web:0.1.0
build: .
{your-herokuapp-xxxxx}にはこのプロキシのドメインに置き換えて下さい。
HerokuにPushする
最後にイメージを作って、HerokuにPushすれば完了です。もちろん{your-herokuapp-xxxxx}はこのプロキシのドメインに置き換えて下さい。
$ docker-compose build --no-cache proxy
$ docker push registry.heroku.com/{your-herokuapp-xxxxx}/web:0.1.0
以上でリバースプロキシが構築できました!
追記(container:release対応)
Container RegistryにDockerイメージをPushした後に、Releaseコマンドが必要になりました。詳しくは以下の記事を参照して下さい。
Heroku Container Registryのcontainer:push後のcontainer:releaseの対応方法
最後に
いかがでしたか?これでHeroku上でNginxでリバースプロキシを構築できるようになったと思います。小さいサービスであればDNS Service Discovery(Herokuの中の人がやたらとセールスしてるやつ)を使わなくてもこれで十分です。では。


コメントを残す