さくらVPSのCentOS7にTomcat8をインストール

せっかくさくらVPSを契約したので(まだお試し期間中ですが)、Tomcatを入れてみることにしました。昔WindowsではTomcatをよく使ってたんですが、Linuxでやると勝手が違いました。

 

まとめ

  • yumリポジトリ―にないっぽい?ので、手動でダウンロードしてインストール
  • systemctlのしきたりにのっとってサービスに登録
  • firewalldで8080番ポートを開ける
  • Tomcat起動が無茶遅いことへ対処
  • 80番でアクセスしたいのでfirewalldでポートフォワードの設定

Tomcatのダウンロードとインストール

このあたりを参考にしてやりました。

 TomcatのWebサイトに書いてるダウンロードURLからダウンロードして、展開するだけっぽいです。お手本にならってインストール先は /opt 以下に。今回はrootじゃなくてちゃんとtomcatユーザー作りましたよ。

ここではダウンロード、展開とsystemctlのサービスの登録までで、ポート関連は次。

 

8080ポートを開ける

Tomcatのデフォルトポートは8080なので、8080番ポートを開ける必要があります。ここを参考にしてやりました。

CentOS7 で Tomcat のポートを解放する Firewall 設定方法: 私的な技術メモ

 

パスを間違えてて無駄にはまる

/etc/systemd/system/tomcat.service のExecStartとかに記述するtomcatのパスを間違えてて、無駄にはまりました。Linuxビギナーだとエラーを見てもtomcat.shが呼ばれてさえいないということが分からないんですよね~

Tomcat自体のログはTomatをインストールしたディレクトリの下の log/catalina.out なので、少なくともTomcatが起動されようとしていれば、ここにログが記録されるはずです。↓Tomcatのログの場所

 /opt/apache-tomcat-xxx/logs/catalina.out

 

とりあえず、さくらVPSのCentOS7上でTomcat8を起動して、うちのブラウザからアクセスできました。

 

Tomcatの起動が無茶遅い

一応ブラウザからアクセスできたはできたんですが、Tomcatを再起動したときとかの起動が無茶苦茶遅いです。catalina.outを見てみると、ROOTのデプロイ処理のとこで5分くらい止まっています。

 
...
23-Nov-2017 00:49:05.236 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
23-Nov-2017 00:49:05.237 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.23
23-Nov-2017 00:49:05.245 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/opt/apache-tomcat/webapps/ROOT] ←ここで5分ぐらいフリーズ
23-Nov-2017 00:54:32.464 WARNING [localhost-startStop-1] org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [326,951] milliseconds. ←セッションID作成に326秒もかかってる
23-Nov-2017 00:54:32.501 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/opt/apache-tomcat/webapps/ROOT] has finished in [327,256] ms
...

 

というわけでエラーメッセージでぐぐったら、回答発見。グーグルさん便利だわ~

java - Tomcat 8 hangs on startup while deploying webapp. Possibly related to entropy generation - Server Fault

HowTo/FasterStartUp - Tomcat Wiki

セッションIDの初期化に使われるSecureRandomのrandomというのが無茶苦茶遅いらしい。このアルゴリズムをあまり厳密でない?urandomにすればOKとのこと。

 

 JREjava.securityを書き換えてもいいらしいけど

乱数生成によるJVM遅延に対処する | Java好き

 

ここでは、以下のページを参考にTomcatにわたすJVMのパラメータで指定することにしました

How To Install Apache Tomcat 8 on CentOS 7 | DigitalOcean

 

 /etc/systemd/system/tomcat.service に以下の1行を追加

[Unit]
Description=Apache Tomcat 8
After=syslog.target network.target

[Service]
User=tomcat
Group=tomcat
Type=oneshot
PIDFile=/opt/apache-tomcat-xxx/tomcat.pid
RemainAfterExit=yes

Environment='JAVA_OPTS=-Djava.security.egd=file:/dev/./urandom'

ExecStart=/opt/apache-tomcat-xxx/bin/startup.sh
ExecStop=/opt/apache-tomcat-xxx/bin/shutdown.sh
ExecReStart=/opt/apache-tomcat-xxx/bin/shutdown.sh;/opt/apache-tomcat-xxx/bin/startup.sh

[Install]
WantedBy=multi-user.target

 

Tomcatに80番ポートでアクセスする

Apache(HTTPサーバー)と連携とかさせずに、Tomcat単体で運用したいと思ったのですが、Tomcatのserver.xmlのポートを8080から80に変えるだけじゃダメっぽい。この記事によると、80番は特別なものらしく、ユーザ権限では使わしてくれないらしい。

Tomcatサーバに80番ポートでアクセスする。 | 三度の飯とエレクトロン

ポートフォワードでやればいいらしいけど、iptablesじゃなくてfirewalldの例が見つからない。Tomcatの例そのものはなかったけど、このあたりを参考にやりました。

centos7 - How to port forward with firewalld depending on source IP - Server Fault

CentOS7のfirewalldをまじめに使うはじめの一歩(systemdも少し) - Qiita

https://fedoraproject.org/wiki/Firewalld?rd=FirewallD

 

[root@xxx ~]# firewall-cmd --permanent --zone=public --add-forward-port=port=80:proto=tcp:toport=8080 ←このコマンドで追加
success
[root@xxx ~]# firewall-cmd --list-all --zone=public
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: dhcpv6-client ssh openvpn http tomcat
  ports:
  protocols:
  masquerade: yes
  forward-ports: port=80:proto=tcp:toport=8080:toaddr= ←追加されてるぽい
  source-ports:
  icmp-blocks:
  rich rules:
[root@xxx ~]# cat /etc/firewalld/zones/public.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="dhcpv6-client"/>
  <service name="ssh"/>
  <service name="openvpn"/>
  <service name="http"/>
  <service name="tomcat"/>
  <masquerade/>
  <forward-port to-port="8080" protocol="tcp" port="80"/> ←設定ファイル上でも追加されてるっぽい
</zone>
[root@xxx ~]# firewall-cmd --reload
success

 

これでめでたく、80番ポートでTomcatにアクセスできました!

Tomcatのsever.xmlはいじってなくてproxyPortの記述とかしてないんですが、まだhelloサーブレットぐらいしか作って動かしてないので、もしかしたら必要なのかも。

あと、この前にApache(tomcatじゃなくてhttpd)が動いてるときはsystemctlでhttpdを停止して自動起動も無効にしておきます。

 

(追記)ルールを削除する場合は、addの部分をremoveにしてやるとOKでした。あと--list-allコマンドで表示されるのはリロード後かも。

[root@xxx ~]# firewall-cmd --permanent --zone=public --remove-forward-port=port=80:proto=tcp:toport=8080

参考 Introduction to FirewallD on CentOS

To remove the rules, substitute --add with --remove. For example...

 

作ったアプリの配置

自分で作ったアプリは、Tomcatをインストールしたディレクトリの下のwebappの下にディレクトリを作って、その下に必要なファイルをおけば、他に設定を記述しなくても動きます。

 

/opt/apache-tomcat-xxx/webapps

     docs/

     exampes/

     ...

     web1/   ←webappsの下に自分のフォルダを作る

         hoge.html

         hoge.jsp

         WEB-INF/

              classes/

 

web1というディレクトリを作って、その下にhoge.htmlを作ったら、ブラウザから

http://xxxxx/web1/hoge.html

のURLでアクセスできます。

サーブレットなどJavaのクラスファイルはWEB-INF/classes以下に置きます。サーブレットもWebアノテーション( @WebServlet("/hello")とか )使えますし、比較的簡単。