Edited at

Clojure Luminus Webアプリケーションのデプロイ

More than 3 years have passed since last update.

Luminusのドキュメントのdeploymentの節( http://www.luminusweb.net/docs/deployment.md )の勝手な和訳。

2016年02月28日時点の内容に基いています。


原文の最新のソースは: https://github.com/luminus-framework/luminus/blob/master/resources/md/deployment.md



Deployment


Contents


  1. Running Standalone

  2. Deploying on Immutant App Server

  3. Deploying to Tomcat

  4. VPS Deployment

  5. Application deployment

  6. Fronting with Nginx

  7. Setting up SSL

  8. Heroku Deployment

  9. Enabling nREPL


Running Standalone

アプリケーションをスタンドアローンで実行できるようにするには、単純にこう実行すればOKです。

lein uberjar

出来上がったjartargetフォルダにあります。次のように実行できます。

java -jar myapp.jar

デフォルトでは、スタンドアローンのアプリケーションは、起動に組み込みのImmutantサーバを使用します。しかしながら、例えば+jettyなどのprofileを使ったとしたら、代わりに別のサーバが使用されます。独自のポート番号を指定するには$PORT環境変数をセットする必要があります。例をあげると:

export PORT=8080

java -jar myapp.jar


Deploying on Immutant App Server

Immutantアプリケーションサーバのデプロイについては、Immutantの公式のドキュメントで概略されているステップをなぞってみてください。Linodeにも、Ubuntu14.04上でImmutantとWildFlyを使ったLuminusアプリケーションのデプロイの仕方についての手引きがあります。


Deploying to Tomcat

Apache Tomcat のようなコンテナにアプリケーションをデプロイするためにはWAR形式のアーカイブを生成する必要があります。これは、+warprofileを使用すると同梱されるlein-uberwarプラグインだけがサポートしています。

lein-uberwarプラグインを有効にするには、project.cljファイルに次の設定を手動で追加してください。

:plugins [...

[lein-uberwar "0.1.0"]]

:uberwar {:handler <app>.handler/app
:init <app>.handler/init
:destroy <app>.handler/destroy
:name "<app>.war"}

WARを作成するためにアプリケーションをパッケージすることができます。こう実行します。

lein uberwar

次に、生成された<app>.warを単純にTomcatのwebappsフォルダにコピーすればOKです。例えば:

cp target/<app>.war ~/tomcat/webapps/

すると、あなたのアプリケーションはTomcatを起動したときに/<app>コンテキストで利用可能になります。アプリケーションをルート・コンテキストにデプロイしたかったら、単にwebapp配下にWARをROOT.warという名前にしてコピーすればOKです。


VPS Deployment

DigitalOceanのような仮想プライベート・サーバ(VPS)は、Clojureアプリケーション向けの安価なホスティング・オプションを提供しています。あなたのDigitalOceanサーバをセットアップするにはこの手引きにとおりやってください。いったんサーバが作成されると、ここに書かれているようにUbuntuをインストールすることができます。最終的に、この手順に従ってあなたのUbuntuにjavaをインストールします。以降で示す手順は、Ubuntu15.04かそれより新しいバージョンに対応しています。


Application deployment

このステップでは、サーバにあなたのアプリケーションをデプロイし、サーバを起動すると自動でアプリケーションが開始することを確認します。これを実現するのにsystemdを使用します。あなたのアプリケーションを実行するdeployユーザをを作成してください。

sudo adduser -m deploy

sudo passwd -l deploy

あなたのアプリケーション用に、サーバ上に/var/myappのようなディレクトリを作成してください。そして、scpを使ってサーバにアプリケーションをアップロードしてください。

$ scp myapp.jar user@<domain>:/var/myapp/

ここまできたら、アプリケーションが起動可能か一度テストしてみるべきです。sshを使ってサーバに接続し、アプリケーションを実行します。

java -jar /var/myapp/myapp.jar

もし全てうまくいっていると、アプリケーションはローカルで起動します。次のコマンドでアプリケーションが期待通り動いているか確認します。

curl http://127.0.0.1:3000/

あなたのアプリケーションは、今やサーバ上でhttp://<domain>:3000でアクセスすることも可能です。もし、アプリケーションがアクセスできなかったら、ファイヤーウォールがこのポートのアクセスを許可しているか確認してください。あなたが利用しているVPSのプロバイダによっては、3000番ポートに対するアクセス・ポイントを作成する必要があるかもしれません。

ここで、アプリケーションのインスタンスを一度停止して、アプリケーションのライフサイクルを管理するsystemdの設定を作成しましょう。とりわけ、サーバ起動時にアプリケーションが開始することに注意しましょう。/lib/systemd/system/myapp.serviceというファイルを作成し、中身を次のとおりにします。

[Unit]

Description=My Application
After=network.target

[Service]
WorkingDirectory=/var/myapp
EnvironmentFile=-/var/myapp/env
Environment="DATABASE_URL=jdbc:postgresql://localhost/app?user=app_user&password=secret"
ExecStart=/usr/bin/java -jar /var/myapp/myapp.jar
User=deploy

[Install]
WantedBy=multi-user.target

デフォルトのJVMはかなりアグレッシブなメモリの使い方をすることに注意してください。もしJVMが使うメモリの量を減らしたかったら、 次の1行を[Service]設定に追加することができます。

[Service]

...
_JAVA_OPTIONS="-Xmx256m"
ExecStart=/usr/bin/java -jar /var/myapp/myapp.jar

この設定は、JVMに使用を許可するメモリの最大量を制限します。ここまでくると、次のコマンドで、システムに再起動がかかるたびに毎回アプリケーションを開始するようにsystemdに伝えることができます。

sudo systemctl daemon-reload

sudo systemctl enable myapp.service

システムが再起動するとき、あなたのアプリケーションは開始しリクエストを処理する準備が整います。テストしたくなるんじゃないでしょうか。単純にあなたのマシンを再起動し、プロセスを確認してください。

ps -ef | grep java

このコマンドを実行すると、何かこんな感じのを返します。UIDに注目してください。これがdeployになっているべきです。rootのままになっていたら重大なセキュリティ・リスクになってしまうでしょう。

deploy     730     1  1 06:45 ?        00:00:42 /usr/bin/java -jar /var/mysite/mysite.jar


Fronting with Nginx

次のコマンドでNginxをインストールしてください。

$ sudo apt-get install nginx

次に、/etc/nginx/sites-available/defaultにデフォルトの設定のバックアップを行って、それをあなたのアプリケーション独自の設定ファイルに置き換えてください。例えばこんなふうに:

server{

listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name localhost mydomain.com www.mydomain.com;

access_log /var/log/myapp_access.log;
error_log /var/log/myapp_error.log;

location / {
proxy_pass http://localhost:3000/;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
}
}

こう実行してNginxを再起動してください。

sudo service nginx restart

それから、アプリケーションがhttp://<domain>で利用可能なことをテストしてください。

追加で、アプリケーションの静的リソースをNginxに配布させるように設定することもできます。これをやるには、全ての静的リソースがstaticなどの共通の接頭辞を使って配信されることを保証しなければいけません。次に、プロジェクトのフォルダで次のようなコマンドを実行して、resources/public/staticフォルダをアプリケーションからサーバ上の/var/myapp/staticなどの場所にアップロードしてください。

scp -r resources/public/static user@<domain>:/var/myapp/static

次の追加設定オプションを、Nginxの設定のserverセクション以下に追記してください。

location /static/ {

alias /var/myapp/static/;
}

http://<domain>/staticへのあらゆるリクエストについて、あなたのアプリケーションを迂回しその代わりに直接配信するようにNginxさせます。

圧縮を有効にするために、次の設定があなたの/etc/nginx/nginx.confに存在することを確かめてください。

gzip on;

gzip_disable "msie6";

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;">


Setting up SSL

もしあなたのサイトがなんらかのユーザ認証を行うなら、HTTPSを使いたいでしょう。まず必要なのは、SSL証明書とその鍵です。この2つをそれぞれcert.crtcert.keyと呼びます。


Setting up SSL Certificate using Let's Encrypt

インストール・ツールをダウンロードし、次のコマンドで証明書を生成してください。

git clone https://github.com/letsencrypt/letsencrypt

cd letsencrypt
/letsencrypt-auto certonly --email <you@email.com> -d <yoursite.com> -d <www.yoursite.com> --webroot --webroot-path /var/www/html

追加で、証明書を自動で更新するためにCronのジョブをセットアップしてください。rootでこう実行することでcrontabが更新できます。

su

crontab -e

次の1行を追加してください。

0 0 1,15 * * /path-to-letsencrypt/letsencrypt-auto certonly --keep-until-expiring --email <you@email.com> -d <yoursite.com> -d <www.yoursite.com> --webroot --webroot-path /var/www/html

OpenSSLのデフォルトを使用する代わりに、より強力なDHEパラメータを生成しましょう。これは、鍵交換に1024-bitの鍵を込めます。

cd /etc/ssl/certs

openssl dhparam -out dhparam.pem 4096

次に、/etc/nginx/sites-available/default内の設定を次のように更新したくなるでしょう。

server {

listen 80;
return 301 https://$host$request_uri;
}

server {

listen 443;
server_name localhost mydomain.com www.mydomain.com;

ssl_certificate /etc/letsencrypt/live/<yoursite.com>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<yoursite.com>/privkey.pem;

ssl on;
ssl_prefer_server_ciphers on;
ssl_session_timeout 180m;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'AES256+EECDH:AES256+EDH';
ssl_dhparam /etc/ssl/certs/dhparam.pem;
add_header Strict-Transport-Security 'max-age=31536000';

access_log /var/log/myapp_access.log;
error_log /var/log/myapp_error.log;

location / {

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# Fix the “It appears that your reverse proxy set up is broken" error.
proxy_pass http://localhost:3000;
proxy_read_timeout 90;

proxy_redirect http://localhost:3000 https://mydomain.com;
}
}

上記の設定はNginxに、HTTPのリクエストをHTTPSにリダイレクトし、配信でさっきの証明書を使用するにようにさせます。

最終的に、次のコマンドを実行することによって、特定のポートだけを許可するようにファイヤー・ウォールを設定してください。

$ sudo ufw allow ssh

$ sudo ufw allow http
$ sudo ufw allow https
$ sudo ufw enable

SSL Server Testを使用すれば、SSLの設定をテストすることができます。


Heroku Deployment

まず、GitHeroku toolbeltがインストールされているか確認し、以下のステップに従ってください。

やりたかったらで良いですが、アプリケーションがローカルで起動することをテストしてみてください。こうすればOKです。

heroku local

ここまできたら、あならのgitリポジトリを初期化し、アプリケーションのコードをコミットすることができます。

git init

git add .
git commit -m "init"

Herokuにあなたのappを作成

heroku create

任意で、アプリケーションで使うデータベースを作成

heroku addons:create heroku-postgresql

接続設定は、appのadd-ons配下のHeroku dashboardにあります。

アプリケーションをデプロイ

git push heroku master

これで、あなたのアプリケーションはHerokuにデプロイできるはずだ。データベースを更新または初期化するために

heroku run lein run migrate

さらなる手順は、公式ドキュメントを見てください。


Enabling nREPL

LuminusはサーバのREPLに接続することを可能にするnREPLのセットアップを備えています。この機能は、稼働中のアプリケーションをhotfixするだけでなくデバッグ全般に便利です。nREPLのサポートを有効にするには、NREPL_PORT環境変数に利用したいポート番号を設定します。

export NREPL_PORT=7000

REPLの接続をテストするなら、単に次のコマンドを実行してください。

lein repl :connect 7001

ローカルのREPLに接続するのと全く同じようにして、好きなIDEからリモートのREPLに接続することができます。

リモートのサーバでnREPLを起動するとき、SSHを使ってローカル・マシンにREPLのポートをフォワードすることをおすすめします。

ssh -L 7001:localhost:7001 remotehost