Help us understand the problem. What is going on with this article?

Tomcat の初期設定まとめ

はじめに

最近は Jetty に押されている感もありますが、Apache Tomcat は今でも各ディストリビューションに rpm が用意されていたりと、よく使われる Java AP サーバです。しかし、そのわりには初期設定がイマイチなことが多く、インストール後いろいろと設定を変更しなければならなくなります。にも関わらず、ドキュメントを読むだけでは、どう設定すれば適切と言えるのかわかりずらいところがあります。
この文書は、いつも行う手順を自分なりにまとめたものです。こうした方が良いなどあれば追記しますのでコメントでご指摘頂けると幸いです。なお、本稿を書いている時点でのバージョンは、Tomcat 8.5 です1

2017/01/31 追記:フロントエンドサーバから HTTP で接続する場合の設定を追記しました。

不要な webapp の削除

tomcat.apache.org の配布物を展開した場合、ROOT, docs, examples, manager, host-manager が最初から含まれています。本番環境では、ROOT, docs, examples はそもそも不要なのでフォルダごと削除していいですし、これから書くように manager, host-manager も削除すべきです。なお、最近の Linux ディストリビューションの場合、rpm で入れると webapps は空の状態でインストールされるようです。

manager は以前のバージョンではデプロイに必要になる場合もありましたが、最近のバージョンでは、webapps 以下に war ファイルを置くだけでデプロイすることができますし、追加の設定も war ファイルの META-INF/context.xml に書くことが可能なので削除しても特に困ることはありません。Web サーバ側でアクセス可能なパスに制限をかけることが出来るとはいえ、設定に間違いがあれば侵入されてしまう可能性もあるわけですから、セキュリティを考えれば、管理機能が Web 側からアクセス出来る場所にあるというのは望ましくないと思います。

host-manager も同様に仮想ホスト機能の管理画面ですが、そもそも通常は必要にはならないし、conf/server.xml を直接修正すればいいだけです。

不要なポート使用の停止

conf/server.xml の Connector にアプリケーションへの接続用ポートの設定、Server にシャットダウンポートの設定があります。

デフォルトでは、HTTP, AJP の設定が有効になっています。通常、AP サーバを立てる場合は、フロントエンドサーバとして Web サーバを立て、その後ろで動作させるのが一般的だと思います。その場合には、HTTP で接続するか AJP で接続するかによって設定を変える必要があります。

フロントエンドサーバと AP サーバを AJP で接続する場合

AJP は、Apache が策定した Web サーバと Java AP サーバ間専用の接続プロトコルです。パフォーマンスとしてはどちらでもさほど変わらないようなのですが、 AJP で接続した場合、Web サーバと AP サーバが一体であるかのように振る舞うため実務的なメリットが多くあります。例えば、HTTPS の処理を Web サーバ側で行う場合でも request.isSecure() が true を返しますし、request.getRemoteAddr() がきちんとクライアントのアドレスを返します。統合 Windows 認証の認証情報を受け取りたい場合にも AJP を使うことで実現できます2

AJP で接続する場合には、(特に本番環境では)HTTP ポートは閉じてしまっていいですし、逆に AJP を使用しないのであれば、AJP ポートを閉じてしまって構いません。ポートを閉じたい場合は、該当の Connector タグをコメントアウトして Tomcat を再起動してください。

フロントエンドサーバと AP サーバを HTTP で接続する場合

フロントエンドサーバと AP サーバの接続に HTTP を使う場合、特に何も設定を行わないとアクセスログには Web サーバの IP アドレスが記録されてしまいます。このような問題に対応するため、最近のフロントエンドサーバは、特別な HTTP ヘッダ(プロキシプロトコル3)をバックエンドサーバに受け渡します。

HTTPヘッダ 説明
X-Forwarded-For カンマで区切られた経由したプロキシサーバ名のリスト
X-Forwarded-Proto リクエストされたプロトコル(例:https)

Tomcat では、RemoteIpValve4 を設定することでフロントエンドサーバを経由したアクセスでも直接アクセスしたかのように情報を取得することができます。

conf/server.xml
<Valve className="org.apache.catalina.valves.RemoteIpValve"
       protocolHeader="X-Forwarded-Proto" />

シャットダウンポートの取り扱い

後はシャットダウンポートの取り扱いですが、サービス起動時は OFF にして問題ないとの記載があります。Windows環境ではサービス起動が一般的ですから問題ないとは思いますが、Linux 環境では daemon のスクリプト中で catalina.sh を使って起動しているようなので OFF にすべきか判断が難しいところです5

シャットダウンポートを停止する場合はポート番号に -1 を設定し Tomcat を再起動してください。

<Server port="-1" shutdown="SHUTDOWN">

ログの整理

Tomcat はデフォルトで多くのログファイルを出力するため、いったいどのログに何が出力されるのか大変わかりずらいです。環境によって多少の違いがあるようなのですが、デフォルトでは次のようになっています。

ログファイル 出力内容 設定箇所
catalina.out6 標準出力(catalina.logの内容を含む)+標準エラー出力 catalina.sh
catalina.YYYY-MM-DD.log Tomcat自体のログ logging.properties
localhost.YYYY-MM-DD.log ホスト共通の ServletContext#log logging.properties
manager.YYYY-MM-DD.log manager webapp の ServletContext#log logging.properties
host-manager.YYYY-MM-DD.log host-manager webapp の ServletContext#log logging.properties
localhost_access_log.YYYY-MM-DD.txt ホスト共通の アクセスログ server.xml

まず、このうち manager.YYYY-MM-DD.log と host-manager.YYYY-MM-DD.log は webapp 自体を削除してしまっているので不要です。また、catalina.YYYY-MM-DD.log は起動したコンソールにログを出力するように設定されていますが、サービスとして使う場合には単にふたつのログファイルに同じ内容が出力されてしまっているので、これも抑止してしまって構いません。

conf/logging.properties
handlers = 1catalina.org.apache.juli.AsyncFileHandler, 2localhost.org.apache.juli.AsyncFileHandler
#   , 3manager.org.apache.juli.AsyncFileHandler, 4host-manager.org.apache.juli.AsyncFileHandler, java.util.logging.ConsoleHandler

.handlers = 1catalina.org.apache.juli.AsyncFileHandler
#   , java.util.logging.ConsoleHandler

1catalina.org.apache.juli.AsyncFileHandler.level = FINE
1catalina.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.AsyncFileHandler.prefix = catalina.

#2localhost.org.apache.juli.AsyncFileHandler.level = FINE
#2localhost.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
#2localhost.org.apache.juli.AsyncFileHandler.prefix = localhost.

#3manager.org.apache.juli.AsyncFileHandler.level = FINE
#3manager.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
#3manager.org.apache.juli.AsyncFileHandler.prefix = manager.

#4host-manager.org.apache.juli.AsyncFileHandler.level = FINE
#4host-manager.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
#4host-manager.org.apache.juli.AsyncFileHandler.prefix = host-manager.

#java.util.logging.ConsoleHandler.level = FINE
#java.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter

org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.AsyncFileHandler

#org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO
#org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = 3manager.org.apache.juli.AsyncFileHandler

#org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/test].level = INFO
#org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/test].handlers = 4host-manager.org.apache.juli.AsyncFileHandler

これで、ログファイルは、catalina.out、catalina.YYYY-MM-DD.log、localhost.YYYY-MM-DD.log、localhost_access_log.YYYY-MM-DD.txt だけになりました。ここからはプロジェクトによりますが、通常、アプリケーションのログは ServletContext#log メソッドを使わずに logback などのアプリケーション固有のログ出力機能を使うことが多いのではないでしょうか。多くの場合、ServletContext#log が使われるのは、設定ミスなどによるアプリケーションの起動が失敗した場合のみでしょう。そう考えると catalina.YYYY-MM-DD.log に統合した方が良さそうです。

conf/logging.properties
handlers = 1catalina.org.apache.juli.AsyncFileHandler
.handlers = 1catalina.org.apache.juli.AsyncFileHandler

1catalina.org.apache.juli.AsyncFileHandler.level = FINE
1catalina.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.AsyncFileHandler.prefix = catalina.

org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 1catalina.org.apache.juli.AsyncFileHandler

これで、catalina.out、catalina.YYYY-MM-DD.log、localhost_access_log.YYYY-MM-DD.txt のみとなりました。catalina.out は標準(エラー)出力だけが記録されるので、ほぼ用済みなのですが、何らかの理由でシェルからの起動時にエラーが発生した場合には原因究明に必要となるので、そのままにしておきます。もし、抑止したいという場合には、bin/setenv.sh にて CATALINA_OUT に /dev/null を指定することが可能です。

最後にアクセスログです。Tomcat では、アクセスログは拡張機能のひとつとして実装されているため、logging.properties ではなく server.xml に設定があります。

conf/server.xml
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
       prefix="localhost_access_log" suffix=".txt"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />

Web サーバと併用する場合には、Web サーバ側で同様のログが取れるため、コメントアウトしてもかまわないとは思います。Web サーバと AP サーバの接続に失敗するような場合だけ戻せばよいのではないでしょうか。

Tomcat 単独で動作させる場合には、むしろ Apache と同じログ形式で出力した方が便利です。まず、ファイル名ですが prefix、suffix を省略すると Apache のデフォルト・ログ・ファイル名と同じ access_log になります。pattern に ついても simple を指定すると Common Log Format で出力され、combined を指定すると Combined Log Format で出力されます7

conf/server.xml
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
       pattern="combined" />

なお、RemoteIpValve と併用する場合は、requestAttributesEnabled="true" を指定する必要があります。

JavaVM オプションの設定

本番環境で AP サーバを使用する場合には、メモリの上限を上げるために JavaVM の起動オプションを設定することが多いと思います。通常の Java アプリであれば引数を設定するだけですが、Tomcat の場合は、起動用のシェルスクリプトが用意されているため、別の方法で設定する必要があります。

設定方法は、bin/catalina.sh(Windows であれば bin/catalina.bat)の中に書かれていますが、bin/setenv.sh(Windows の場合は bin/setenv.bat)を作成しそこに変数を定義すると反映されます8

設定できる変数のうち、主なものを列挙します。

変数名 説明
CATALINA_OPTS Tomcat 起動時の JavaVM オプションを指定します。JAVA_OPT でも指定できますが、こちらに設定すると Tomcat のすべてのコマンド(例えば stop など)にも反映されてしまうため、CATALINA_OPTS に設定するほうが適切です。
JAVA_HOME Tomcat を起動する JavaVM の場所を指定します。
CLASSPATH Tomcat に追加するクラスパスを指定します。グローバルな CLASSPATH 環境変数は無視されるため、こちらに指定する必要があります。

  1. また、Tomcat 上には単独の webapp のみを配置することを想定しています。複数の webapp が必要となる場合には、必ずしも適切な設定ではないかもしれません。 

  2. 認証を通過させる場合には、tomcatAuthentication="false" を設定する必要があります。【参考】Windows Authentication How-To 

  3. RFC7239 で標準化されたようですが、多くのフロントエンドサーバではまだ対応していない場合が多いようです。 

  4. RemoteIpValve Javadoc 

  5. スクリプトを読む限り、シャットダウンポートを使って停止出来ないときはシグナルを送って停止させているので、止めてしまっても問題ないようには見えます。 

  6. Windows の場合には、catalina.out は出力されません。サービスとして起動した場合には代わりに、サービス・プログラムのログ(commons-daemon.YYYY-MM-DD.log)、標準出力のログ(tomcat8-stdout.YYYY-MM-DD.log)、標準エラー出力のログ(tomcat8-stderr.YYYY-MM-DD.log)の3つが出力されます。 

  7. ローテーションはデフォルトで true です。logrotate を使うなどの理由でローテーションをやめたい場合は rotatable="false" を付けます。 

  8. Windows サービスの場合には bin/setenv.bat の内容は反映されないことに注意してください。同フォルダにある Tomcat8w.exe を実行するかタスクトレイの Tomcat アイコンを右クリックし「Configure...」をクリックすると設定画面が立ち上がりますので、そこで設定します。設定内容はレジストリに格納されます。 

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away