[Grails]Nginx経由でGrailsを動かす場合の設定

#参考
[Asset Pipeline Plugin](http://grails.org/plugin/asset-pipeline)


# 概要
Grailsに限らず、JavaベースのWebアプリケーションを公開するために、Webサーバ経由でTomcatなどのサーブレットコンテナにアクセスさせる、という方法が取られます。
Tomcatはポート8080で動いていて、Webサーバはポート80番で動いている。
ユーザがWebサーバにアクセスしてくると、処理をTomcatに流す、という感じです。

今回、NginxをWebサーバとして場合の設定方法をまとめます。

#Grailsの設定

##前提条件
大前提として、画像もCSSもJavaScriptも[Asset Pipeline Plugin](http://grails.org/plugin/asset-pipeline)経由で扱うようにする必要が有ります。
Asset Pipelineの簡単な使い方は[[Grails]Asset-Pipelineプラグインのメモ](http://qiita.com/saba1024/items/2ae86dd1878e4bebe60c)を参照してください。
また、今回はGrailsアプリケーションのコンテキストルートを`/`として、Tomcatにデプロイするwarファイル名もTomcatのメインアプリケーション扱いになる`ROOT.war`とします。

Grailsのデフォルトのコンテキストルートは、Config.groovyのどこかに以下の行を追加することで変更可能です。

```groovy:grails-app/conf/Config.groovy
grails.app.context = '/'
```

この状態でGrailsをrun-appで起動すると、http://localhost:8080/ でGrailsアプリケーションにアクセスできるようになります。

また、`grails war`コマンドで生成されるデフォルトのwarファイル名はBuildConfig.groovyに以下の行を追加することで変更可能です。

```groovy:grails-app/conf/BuildConfig.groovy
grails.project.war.file = "target/ROOT.war"
```

##設定
開発環境であれば、多くの場合そのままGrailsが起動するTomcatにアクセスすると思われますので、この場合は特に何も問題はありません。
しかし、本番サーバでNginxなどからアクセスが経由されてくる場合は、画像ファイルなどのURLの扱いが原因で、デフォルトでは404となってしまいます。
そこで、configファイルに以下の行を追記します。

```groovy:grails-app/conf/Config.groovy
environments {
    development {
        grails.logging.jul.usebridge = true
    }
    production {
        grails.logging.jul.usebridge = false
        // TODO: grails.serverURL = "http://www.changeme.com"
        // 以下の行を追加
        grails.assets.storagePath = "/tmp/hoge"
    }
}
```

そして、実際にGrailsアプリケーションが動作するサーバ上で、上記で追加したパスのディレクトリ（/tmp/hoge）を作成して、Tomcatから書き込めるような権限にしておきます。

**注意！このサンプルは/tmp配下にディレクトリを作成しましたが、Linuxディストリビューションによってタイミング等は異なりますが、/tmpディレクトリは定期的に削除されます。実際に運用する際にはTomcatからの書き込み権限が与えられる場所で、適切は場所を選択するようにしてください。**


#Nginxの設定

##前提条件
今回、バーチャルホストを使っている。
ドメインやパスなどは適宜読み替えてください。

また、今回は用意したファイルは、nginxのデフォルトの設定ファイルから自動的に読みこまれるようにしています。

##設定

```nginx:/etc/nginx/conf.d/example.com.conf
server {
    listen 80; 
    server_name example.com;
    index index.html index.htm index.php;

    # settings for access log 
    access_log /var/log/nginx/example.com.access.log;
    # settings for error log 
    error_log /var/log/nginx/example.com.error.log;

    location / { 

        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;

        proxy_pass http://127.0.0.1:8080;
        proxy_cookie_path / /;
        proxy_set_header   X-Forwarded-For $remote_addr;
    }   

    location ^~/assets {
        alias /tmp/hoge;
    }   
}
```

基本的にはコレでNginxを起動すればOKです。
GrailsアプリケーションがTomcatにデプロイされるタイミングで、[Asset Pipeline Plugin](http://grails.org/plugin/asset-pipeline)で扱われるファイルは全て、Config.groovyで指定した`/tmp/hoge`ディレクトリ配下に展開されます。

そして、Nginxが`/assets/`へのアクセスは自動的に、`/tmp/hoge`へマッピングしてくれます。（alias）

#問題点
Tomcat7から利用できるようになったパラレルデプロイですが、今回のように無条件に[Asset Pipeline Plugin](http://grails.org/plugin/asset-pipeline)用のディレクトリが1箇所に固定されている場合に問題が発生します。
というのも、後から起動したアプリケーションが`/tmp/hoge`ディレクトリを上書きしてしまうためです。
[Asset Pipeline Plugin](http://grails.org/plugin/asset-pipeline)で扱うファイルに変化がなければ問題にはならないと思われますが、そういった状況毎にデプロイ方法を変えるのは時代の流れに逆行してしまうので、素直にTomcatの停止-> 古いROOTディレクトリの削除 -> ROOT.warの入れ替え -> Tomcatの起動を行うのがベターだと思います。

#まとめ
自分が実際にハマったのでまとめました。
コンテキストが`/`じゃなくても、Nginxの設定（パス）さえちゃんとしていれば動くんじゃないかなと思います。