TomcatとApache HTTP ServerでSpring Bootアプリケーションをデプロイしてみる

「Spring Securityでユーザ認証を実装してみる」では、Spring Securityで簡単なユーザ認証を実装した。 ここでは、UbuntuサーバにTomcatをインストールし、作成したアプリケーションをデプロイしてみる。 また、Apache HTTP Serverをインストールし、アプリケーションをHTTPSで配信してみる。

環境

Ubuntu 16.04.2 LTS 64bit版

$ uname -a
Linux vm-ubuntu64 4.4.0-72-generic #93-Ubuntu SMP Fri Mar 31 14:07:41 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.2 LTS
Release:        16.04
Codename:       xenial

Tomcatのインストール

まず、Tomcat本体とTomcat Managerをインストールする。

$ sudo apt install tomcat8 tomcat8-admin

インストールが終わったら、Tomcat Managerへのアクセスを有効にするため、ユーザを作成する。 ここで、ユーザ名・パスワードは推測不可能なものに変えておくこと。

$ sudo vi /etc/tomcat8/tomcat-users.xml
(snip)
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="USERNAME" password="PASSWORD" roles="manager-gui,admin-gui"/>
</tomcat-users>

Tomcatサーバを再起動し、設定を反映させる。

$ sudo systemctl restart tomcat8

ブラウザから http://localhost:8080/ を開き、Tomcatのデフォルトページが表示されることを確認する。 また、http://localhost:8080/manager/html に設定したユーザ名・パスワードでアクセスし、Tomcat Managerが表示されることを確認する。

WARファイルをデプロイしてみる

Tomcatがインストールできたので、Tomcat ManagerからWARファイルをデプロイしてみる。

まず、「Spring Bootで簡単なWebアプリケーションを書いてみる」で説明した手順に従い、アプリケーションのWARファイルを作成する。

Tomcatでは、WARファイルのファイル名は パス名 + "##" + バージョン番号 + ".war" という命名規約に従って扱われる。 なお、配置するパスが / の場合はパス名を ROOT とする。 また、バージョン番号の比較は単純な文字列比較で行われるため、ゼロパディングすることが推奨されている。

配置するパスを /、バージョン番号を 001 とし、作成したWARファイルを ROOT##001.war にリネームする。 これを、Tomcat Managerからファイルアップロードし、デプロイする。

f:id:inaz2:20170424195008p:plain

アップロードが完了した後、http://localhost:8080/ にアクセスすると、デプロイしたアプリケーションが表示される。

アプリケーションを更新する際には、パス名をそのままに、バージョン番号の数字を上げたWARファイルを新たにデプロイする。 これにより、古いバージョンに接続しているセッションはそのままに、新規セッションが新バージョンに接続される(Parallel Deployment)。 ただし、同時に複数バージョンのアプリケーションを動作させることになるため、メモリ使用量に注意が必要である。

Apache HTTP Serverと連携してHTTPS対応してみる

Tomcatは簡易HTTPサーバとしても機能するが、パフォーマンスの観点からApache HTTP Server(以下Apache)と連携させて使うことが多い。 そこで、Apacheをインストールし、HTTPSでアプリケーションを配信してみる。 なお、HTTPの場合もSSLに関連する部分を除いて同様に行えばよい。

まず、TomcatAJPコネクタを有効にする。 具体的には、下記の箇所のコメントを外す。

$ sudo vi /etc/tomcat8/server.xml
    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

Tomcatを再起動し、設定を反映させる。

$ sudo service tomcat8 restart

次に、Apacheをインストールし、proxy_ajpモジュールとsslモジュールを有効にする。

$ sudo apt install apache2

$ sudo a2enmod proxy_ajp ssl

default-sslをベースに、サイト設定ファイルを作成する。 具体的には、DocumentRootをコメントアウトし、ProxyPassを追記する。

$ sudo cp /etc/apache2/sites-available/{default-ssl,tomcat-ssl}.conf

$ sudo vi /etc/apache2/sites-available/tomcat-ssl.conf
                #DocumentRoot /var/www/html
                ProxyPass / ajp://localhost:8009/

作成したサイト設定を有効にし、Apacheを再起動する。

$ sudo a2ensite tomcat-ssl

$ sudo service apache2 restart

ブラウザから https://localhost/ にアクセスすると、HTTPSでアプリケーションにアクセスできることが確認できる。

f:id:inaz2:20170424193527p:plain

さらに、curlコマンドでレスポンスヘッダを確認してみると次のようになる。

$ curl -v --insecure https://localhost/login
(snip)
> GET /login HTTP/1.1
> Host: localhost
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Mon, 24 Apr 2017 07:56:29 GMT
< Server: Apache/2.4.18 (Ubuntu)
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains
< X-Frame-Options: DENY
< Set-Cookie: JSESSIONID=E49A71C1D34D08184F23B1BF59483BB1; Path=/; Secure; HttpOnly
< Content-Type: text/html;charset=UTF-8
< Content-Language: en-US
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
<
(snip)

上の結果から、Spring SecurityによりStrict-Transport-SecurityヘッダおよびCookieのSecure属性が付与されていることが確認できる。

あとは、通常のApacheと同様に、SSL証明書やログの設定を行えばよい。

実行可能jarとnginxによるデプロイ

Spring Bootでは従来のWARファイルによるデプロイの他に、組み込みtomcatを用いた実行可能jarによるデプロイも可能である。 最近ではTwelve-Factor Appの観点から、実行可能jarとして起動したアプリケーションをnginxで振り分ける方法が好まれることもある。 詳しくは、下記のページを参照。

関連リンク