Tomcat

Jakarta Project で有名なJava サーブレットコンテナです。apache などと連携でき、サーバーサイドJava を 提供するプラットフォームになります。
更新日 2016-09-15

インストール

JRE 7 をインストール

Java の実行環境です。コチラからJava SE 7 (JRE) をダウンロードします。開発環境用としては Java SE 7 (JDK) を選びます(JRE は含まれています)。
// ブラウザからダウンロードしておいてファイル転送する

tar zxvf jre-7u21-linux-i586.tar.gz
ln -s jre-7u21-linux-i586 jre

Tomcat

コチラのTomcat7 をダウンロードします。コレを展開し、任意のフォルダ下(/usr/local 等)に配置します。
cd /usr/local
wget "http://ftp.riken.jp/net/apache/tomcat/tomcat-8/\
v8.0.35/bin/apache-tomcat-8.0.35.tar.gz"

tar zxvf apache-tomcat-8.0.35.tar.gz

ln -s apache-tomcat-8.0.35 tomcat8
// CentOS64bit では以下も必要
yum -y install glibc.i686

起動の設定

chkconfig で登録する事が出来るサービス用起動スクリプトを新規作成しましょう。内容は実にシンプルで $CATALINA_HOME/bin に用意されている起動スクリプト(startup.sh とshutdown.sh) を呼び出すだけです。
vi /etc/rc.d/init.d/tomcat8
 
 #!/bin/sh
 #
 # chkconfig: 35 80 20
 # description: tomcat8

 export JAVA_HOME=/usr/java/jre
 export JRE_HOME=/usr/java/jre
 export PATH=$PATH:/usr/java/jre/bin

 export TOMCAT_HOME=/usr/local/tomcat8
 export CATALINA_HOME=/usr/local/tomcat8
 export PATH=$JAVA_HOME/bin:$PATH

 export JAVA_OPTS="-server -Xms256M -Xmx2560M"
 export CATALINA_OPTS="-server -Xms256M -Xmx2560M"

 export LANG=ja_JP.UTF-8  # set local (japanese log out)

 PROFILEDIR=/var/lock/subsys

 case "$1" in
   start)
     if [ -f $PROFILEDIR/Tomcat ]; then
       echo "Already running Tomcat"
     else
       echo "Starting tomcat: "
       $CATALINA_HOME/bin/startup.sh
       touch $PROFILEDIR/Tomcat
       echo
       sleep 5
     fi
   ;;
  stop)
     if [ -f $PROFILEDIR/Tomcat ]; then
       echo "Tomcat shutdown: "
       $CATALINA_HOME/bin/shutdown.sh
       rm -f $PROFILEDIR/Tomcat
       echo
       sleep 5
     fi
   ;;
  restart)
     echo "Restarting tomcat: "
     $CATALINA_HOME/bin/shutdown.sh
     $CATALINA_HOME/bin/startup.sh
     echo
   ;;
 esac

chmod 755 /etc/rc.d/init.d/tomcat8

// 自動起動するようにリンクを張る
chkconfig tomcat on
サービスとして起動します。正常に起動後、http://localhost:8080/ で管理画面を確認できれば成功です。
service tomcat start

apache2.2 と連動させる (mod_proxy_ajp を利用 [推奨])

apache2.2 からはバックグランドサーバー(Tomcat)との通信プロトコルにAJP1.3 が使えるようになっています。 あっけない程簡単に、意識せずに使えて拍子抜けです。

ProxyPass を使う

例えばhttp://ast.qt-space.com/servlet/ 以下のリクエストをTomcat で処理したい場合。
<Virtualhost *:80>
    ServerName ast.qt-space.com
    DocumentRoot /usr/local/apache2/htdocs/ast

    ProxyPass /servlet/ ajp://localhost:8009/servlet/
</Virtualhost>

mod_rewrite を用いた場合

mod_rewrite からも通常通りに扱えます。複雑なリクエストを処理したい場合はmod_rewrite を使うのがベストです。
RewriteEngine on

RewriteRule ^/servlet/(.*)$		ajp://localhost:8009/servlet/$1		[P,L]
注)Tomcat におけるセッション管理の為のCookie 出力に際してはこのコンテキストパス(この場合/servlet) も一緒に渡される為、 実リクエスト部もコンテキストパスと同じでなければいけません。

カスタマイズ

デフォルト設定では実運用に向かない側面もあるので、適宜カスタマイズしましょう。

localhost:8080 での応答について

この管理画面はセキュリティ上の理由から必要に応じてファイアーウォール等を用いて、 外部からは容易にアクセスできないようにするべきです。またTomcat 側でこのポートを 完全に利用しないように設定するのであれば、設定ファイル(server.xml) を編集して ポート8080 に関するConnector ディレクティブをコメントアウトします。
vi $CATALINA_HOME/conf/server.xml
 <-- Define a non-SSL Coyote HTTP/1.1 Connector on port 8080 -->
// に続くConnector ディレクティブをコメントアウトします。

ファイルの一覧表示を無効にする。

Tomcat はディレクトリパスで終わるURL でアクセスを受けると、そのディレクトリ中の ファイル一覧を表示を行います。実運用ではもちろん好ましくないので無効にします。 Tomcat の設定ファイル(web.xml) を編集し、init-param エレメントにおいて、listings を false にします。Tomcat6 ではデフォルトでfalseなので改めて設定する必要はありません。
vi $CATALINA_HOME/conf/web.xml

<servlet>
	<init-param>
		<param-name>listings</param-name>
		<param-value>false</param-value>

リクエストパラメータにUTF8 エンコーディングを使う

server.xml を編集し、コネクタ部にURIEncoding="utf8" を追記します。
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" enableLookups="false" redirectPort="8443" 
 protocol="AJP/1.3" URIEncoding="utf8" />

URLが見当たらない場合のページを設定

デフォルトでは例外画面が出ますが、見栄えのいい404NotFound 用のページを独自に 準備して表示させる事もできます。$CATALINA_HOME/con/web.xml を編集します。
<!-- 以下を追加-->
<error-page>
<error-code>404</error-code>
<location>/404_notfound.jsp</location>
</error-page>
404_notfound.jsp は自分で作成してね。

起動が遅い

特定の環境で起動速度がとても遅くなります。

コンテキストファイル(context.xml)

コンテキストファイルにはWeb アプリ毎の設定を書きます。Tomcat はこのファイルを読み込んでWeb アプリを有効にします。 Tomcat サイドのserver.xml に直接書く事も出来ますが、autoDeploy の動作によってコンテキスト自体もWeb アプリサイド(/META-INFO/context.xml)に 記述する事ができます。そしてそれは理にかなっています。

/META-INFO/context.xml の作成

WebアプリのフォルダMETA-INFO にcontext.xml を作成します。Context タグ要素からなるシンプルなXML です。autoDeploy されるので、当然docBase 属性は必要ありません。
<Context path="/servlet" debug="0" reloadable="true" crossContext="false"
 allowLinking="true">
</Context>

ルート(/)にコンテキストを配置する

単純に考えるとpath="/" とContext タグ部に書けば良さそうですが、問題アリです。配置するディレクトリをROOT(war ファイルならROOT.war) としないといけません。 Tomcat manager からルートコンテキストを再起動をする際にエラーになるからです。これもハマるポイントです。

セッションについて

ルート以外に配置するとクッキーに含まれるセッションID にルート以外のパスも含まれます。ところが公開するサイトがドメインベースである場合、このパスが異なる 事が原因でセッション維持ができない場合があります。Tomcat ではクッキーのJSESSIONID を参照するため、JSESSIONID=session.getId() を別に追加してやればクリアできます。

認証機能を使う

Tomcat には特定のURL に対して認証によるアクセス制限を設ける事ができます。

レルムの設定

server.xml を編集します。Engine タグ、Host タグ、Context タグのいずれかの子要素として設定します。 デフォルトでも設定されていると思いますが、もしコメントアウトされていたら外します。
<Realm className="org.apache.catalina.realm.MemoryRealm" />

web.xml を編集

対象となるWEB アプリケーションのweb.xml に以下を追加してゆきます。resource-ref 要素以降に 記述します。
<security-constraint>
	<web-resource-collection>
		<web-resource-name>auth_ast</web-resource-name>
		<url-pattern>/ast_admin/*</url-pattern>
	</web-resource-collection>
	<auth-constraint>
		<role-name>ast_auth_role</role-name>
	</auth-constraint>
</security-constraint>
url-pattern は認証を必要とするパスです。ワイルドカードが使えますが、拡張子を指定する場合は フォルダの指定はできません。*.jps もしくは/ast_admin/* といった感じになります。role-name は アクセス許可するロールを指定します。
<login-config>
	<auth-method>BASIC</auth-method>
	<realm-name>auth AST</realm-name>
</login-config>
とりあえずBASIC 認証を試すとします。次に最初に記述したロールをsecurity-role としても 改めて記述します。
<security-role>
	<role-name>ast_auth_role</role-name>
</security-role>
このように記述したロールだけが、アクセス許可用ロールとして使用可能になります。

tomcat-user.xml を編集

ユーザーとパスワードを設定します。
<role rolename="admin-gui"/>
<role rolename="admin-script"/>

<role rolename="manager-gui"/>
<role rolename="manager-status"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>

<role rolename="admin"/>
<role rolename="ast"/>

<user username="admin" password="passwd" 
 roles="admin,manager-gui,manager-status,manager-script,manager-jmx,admin-gui,admin-script,ast"/>

エラー

遭遇したエラーと対策です。

OutOfMemoryError: Java heap space

Exception in thread "ajp-bio-8009-exec-2" java.lang.OutOfMemoryError: Java heap space
Java のヒープメモリが少ないというエラーです。下記の設定でヒープメモリを設定できます。
vi /etc/rc.d/init.d/tomcat
export JAVA_OPTS=$JAVA_OPTS -Xms512m -Xmx1024m
ただしプログラムの設計ミスを疑うべきです。メモリーエラーになるような大量のデータロードが原因かも?