LoginSignup
40
44

More than 3 years have passed since last update.

Linux(CentOS)にApacheとTomcatをインストールしてJavaアプリをデプロイするまで

Last updated at Posted at 2020-05-06

はじめに

Linuxに関する知識を身につけたくて、LinuxサーバのレンタルからJDK, Apache, Tomcatのインストール、自分のローカルPCで作ったJavaアプリケーション(Hello Worldレベル)のデプロイを自力でやってみました。その際にやったこと、詰まったことをどうやって解消したかを書き残したのがこの記事です。
最近はクラウドが圧倒的に主流だけど、クラウドはいろいろブラックボックスすぎると感じています。自分はLinux(インフラ)に関してはとにかく基礎ができていないので、まずはクラウドではなくプレーンなLinuxサーバをレンタルし、そこにアプリケーションをデプロイする作業を自分でやってみる。さらに今後は、アプリケーションを拡張して運用も自分でやってみる。このような試みを通じて、Linuxの基礎を身につけたい。そう思ってこんなことをやってみました。今回はアプリケーションをデプロイするまでで、拡張や運用は今後の話です。デプロイしたのは、アプリケーションと言ってもHello Worldレベルなので、Javaについては書きません。LinuxサーバをレンタルしてApache、Tomcatをインストールして設定してURL叩いたらHello Worldが出た!っていう程度のものです。

実際にやったこと

個人向けレンタルサーバをレンタル

Javaが使える個人向けレンタルサーバをレンタル。今回はさくらインターネットを使うことにした。いろいろあるので自分で探して適切なものを選択しましょう。

OSの確認

CentOS のバージョン確認

これからレンタルしたサーバにJavaやApacheやTomcatをインストールしていくのですが、その前にOSの基本情報を確認。まずは、以下のコマンドで CentOS のバージョンを確認します。
cat /etc/redhat-release

実行結果
CentOS Linux release 7.7.1908 (Core)

CentOSのバージョン7であることがわかる。

アーキテクチャ(OSが32bit, 64bitどちらなのか)を確認

以下のコマンドでOSが32bit, 64bitどちらなのかを確認します。

arch

実行結果(64bit)
X86_64

これは64bitであることを示しています。32bitの場合は以下のように表示されます。

実行結果(32bit)
i686

以下のコマンドでも確認することができます。
uname -a

CentOS 7 の場合は以下のように表示されます。

CentOS7の表示例(64bit)
Linux ik1-344-32350.vs.sakura.ne.jp 3.10.0-957.10.1.el7.x86_64 #1 SMP Mon Mar 18 15:06:45 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

参考ですが、CentOS 6 の場合は以下のように表示されます。

CentOS6の表示例(64bit)
Linux localhost.localdomain 2.6.32-279.2.1.el6.x86_64 #1 SMP Fri Jul 20 01:55:29 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

参考:CentOSのバージョン確認コマンドとアーキテクチャ確認コマンド

パッケージのアップデート

以下コマンドでパッケージをアップデートします。
yum update

本来であれば、現在動作中のプログラムに影響を与えないようにするため、パッケージを指定してアップデートします。しかし今回はレンタルしたばかりで特に何のアプリケーションも稼働していないので、雑にyum updateですべてのパッケージを更新しました。
パッケージを指定するコマンドは以下の通りです。普通はこっちを使って稼働中プログラムに影響を与えないようにしてください。
yum update [パッケージ]

参考:【yum update】yumのパッケージを安全にアップデートする

Java 8 (OpenJDK) インストール

ランタイムだけのインストールで良ければ java-1.8.0-openjdk を、OpenJDK の開発環境もインストールしたければ java-1.8.0-openjdk-devel もインストールします。

Java 8 (JDK) ランタイムのインストール

以下のコマンドを実行してJava 8 (JDK) ランタイムをインストールします。
yum install java-1.8.0-openjdk

java 8 (JDK) 開発環境のインストール

開発環境が必要であれば、以下のコマンドを実行してjava 8 (JDK) 開発環境をインストールします。私は自分のPCで開発してそれをサーバにデプロイするので開発環境はインストールしませんでした。
yum install java-1.8.0-openjdk-devel

インストール完了確認

念のためインストールが完了したのかを確認してみましょう。次のコマンドを打って、インストールした Java のバージョンが表示されれば確認終了です。

実行コマンド
java -version
実行結果
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)

参考:CentOS 7 に Java 8 (OpenJDK) を yum インストールする手順

Apacheインストール

Apacheをインストールしてサービス登録する

以下コマンドでApacheをインストールします。

実行コマンド
yum -y install httpd

サービス登録し、起動します。

実行コマンド
systemctl enable httpd.service
systemctl start httpd.service

以下コマンドでサービスが起動していることを確認します。

実行コマンド
systemctl status httpd.service

active (running)が表示されればOKです。
最後に、テストページ(http://<IPアドレス>)が表示されることを確認します。

参考:さくらクラウドのCentOS7でApacheとTomcatの環境構築した時のまとめ

Tomcatインストール

Apache Tomcat 9 のインストール

まず、Linux 上で Tomcat を動かすための専用ユーザとして tomcat を追加します。

実行コマンド
useradd -s /sbin/nologin tomcat

次に、curl コマンドで Apache Tomcat 9 のダウンロードページから、tar.gz 形式の Apache Tomcat 9 本体をダウンロードします。2020年05月現在はバージョン 9.0.34 が最新版なので次のURLを指定します。最新のバージョンのURLを確認の上で実行してください。

実行コマンド
cd ~
curl -O http://ftp.riken.jp/net/apache/tomcat/tomcat-9/v9.0.34/bin/apache-tomcat-9.0.34.tar.gz

ダウンロードした tar.gz ファイルを解凍して配置します。次のように tar コマンドで解凍し、/opt に配置します。また、解凍した Apache Tomcat の所有者を、先ほど作成した tomcat ユーザの所有とします。

実行コマンド
tar -xzvf ~/apache-tomcat-9.0.34.tar.gz
mv ~/apache-tomcat-9.0.34 /opt
chown -R tomcat:tomcat /opt/apache-tomcat-9.0.34

サービスの作成と登録

CentOS 7 からはサービスを systemd が管理するようになりました。ここでは Apache Tomcat 9 をサービスとして登録します。まずは /etc/systemd/system/tomcat.service を新たに作成して、次のように記述して保存します。これはサービスの定義ファイルです。

tomcat.service
[Unit]
Description=Apache Tomcat 9
After=network.target

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

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

[Install]
WantedBy=multi-user.target

次のコマンドで、作成した定義ファイルの権限を 755 に変更します。

実行コマンド
chmod 755 /etc/systemd/system/tomcat.service

定義ファイルの作成が完了したら、次のコマンドでサービスを有効にします。

実行コマンド
systemctl enable tomcat

以下が表示されればOKです。

実行結果
Created symlink from /etc/systemd/system/multi-user.target.wants/tomcat.service to /etc/systemd/system/tomcat.service.

最後に、http://<IPアドレス>:8080にアクセスし、Tomcatのテストページが表示されることを確認します。

【表示される画面のサンプル】
image.png

このような画面が表示されればTomcatのインストール、およびサービス登録完了です。

参考:Apache Tomcat 9 を CentOS 7 にインストールする手順

ApacheとTomcatの連携

AJP (Apache JServ Protocol)を使ってApacheとTomcatを連携させます。AJP を利用するためには mod_proxy_ajp というモジュールを利用します。

参考:Apache httpd と Tomcat を連携させる方法

apacheの設定

proxy_moduleとproxy_ajp_moduleをLoad

私が apache をインストールしたとき、httpd.confはこの状態でした。

httpd.conf(一部抜粋)

~中略~

#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Statically compiled modules (those listed by `httpd -l') do not need
# to be loaded here.
#
# Example:
# LoadModule foo_module modules/mod_foo.so
#
Include conf.modules.d/*.conf

~中略~

ここに記載されている「/etc/httpd/conf.modules.d」に行ってみると、以下の7個のconfファイルが確認できます。

01-cgi.conf
00-systemd.conf
00-proxy.conf
00-mpm.conf
00-lua.conf
00-dav.conf
00-base.conf

この中の「00-proxy.conf」を開くと以下の設定があります。

00-proxy.conf(一部抜粋)
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

AJP を利用するためには mod_proxy_ajp が必要で、mod_proxy_ajp は mod_proxy モジュールに依存しています。そのため、これら2つのモジュールが必要です。00-proxy.confに上記設定があれば必要なmoduleがちゃんとLoadできています。
ちなみに、こられのモジュール「mod_proxy.so」と「mod_proxy_ajp.so」は、/usr/lib64/httpd/modulesディレクトリに行くと確認できます。
(/etc/httpd配下に/usr/lib64/httpd/modulesへのショートカットがあります)

ProxyPassの設定

httpd.confの一番最後の行に以下のような設定があるため、/etc/httpd/conf.dディレクトリにconfファイルを作成すればその内容が読み込まれるようになっています。

httpd.conf

~中略~

# Supplemental configuration
#
# Load config files in the "/etc/httpd/conf.d" directory, if any.
IncludeOptional conf.d/*.conf

以下の内容で/etc/httpd/conf.dディレクトリにproxy-ajp.confファイルを作成します。

cat /etc/httpd/conf.d/proxy-ajp.conf
<Location /docs/>
  ProxyPass ajp://127.0.0.1:8009/docs/
</Location>

portを8009にしているのは、TomcatがAJP 1.3の通信をport 8009で受け付けているからです。Tomcatの設定はこの後出てきます。
Apacheの設定はこれで完了です。

Tomcatの設定

server.xmlの修正

/opt/apache-tomcat-9.0.34/conf/server.xmlを修正します。修正前は以下のようになっています。

server.xml(修正前)
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

~中略~

    <Connector protocol="AJP/1.3"
               address="::1"
               port="8009"
               redirectPort="8443" />

インターネットからのすべてのアクセスをapache経由にするのであればport 8080での待ち受けは不要になるため、コメントアウトします。
修正後は以下の通りとなります。

server.xml(修正後)
    <!--
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    -->

~中略~

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector protocol="AJP/1.3"
               address="::1"
               port="8009"
               redirectPort="8443" />

これでapacheとTomcatを連携するための設定は完了です。

はまったこと1

上記作業が終わり、http://<IPアドレス>/docsをブラウザに入力したのですが、503エラーがでてアクセスできませんでした。apacheのログ(error_log)を確認したところ、以下のログが出ていました。

Apacheログ
[Sun Apr 26 14:33:39.753098 2020] [proxy:error] [pid 30144] (111)Connection refused: AH00957: AJP: attempt to connect to 127.0.0.1:8009 (127.0.0.1) failed
[Sun Apr 26 14:33:39.753136 2020] [proxy:error] [pid 30144] AH00959: ap_proxy_connect_backend disabling worker for (127.0.0.1) for 60s
[Sun Apr 26 14:33:39.753141 2020] [proxy_ajp:error] [pid 30144] [client 220.100.106.105:51467] AH00896: failed to make connection to backend: 127.0.0.1

最初はこのログの文言を元にいろいろググったのですが、どうやったら解決できるのかまったく見当がつきませんでした。
次にTomcatのログ(catalina.out)を確認したところ、Tomcatを起動する度に以下のログが出力されていることが確認できました。

Tomcat起動時のログ1
18-Apr-2020 16:36:49.322 SEVERE [main] org.apache.catalina.util.LifecycleBase.handleSubClassException Failed to initialize component [Connector[AJP/1.3-8009]]
    org.apache.catalina.LifecycleException: Protocol handler initialization failed
        at org.apache.catalina.connector.Connector.initInternal(Connector.java:1041)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
        at org.apache.catalina.core.StandardService.initInternal(StandardService.java:533)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
        at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:1057)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:584)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:607)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:303)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:473)
    Caused by: java.net.SocketException: Protocol family unavailable
        at sun.nio.ch.Net.bind0(Native Method)
        at sun.nio.ch.Net.bind(Net.java:433)
        at sun.nio.ch.Net.bind(Net.java:425)
        at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:220)
        at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:85)
        at org.apache.tomcat.util.net.NioEndpoint.initServerSocket(NioEndpoint.java:228)
        at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:211)
        at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1141)
        at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1154)
        at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:581)
        at org.apache.catalina.connector.Connector.initInternal(Connector.java:1038)
        ... 13 more

「Protocol family unavailable」とか「Connector[AJP/1.3-8009]」でググったらこのサイトにたどり着きました。どうやらIPv6をサポートしていないサーバでIPv6のアドレス"::1"が指定されていると起きる事象らしい。
"::1"を"0.0.0.0"に書き換えることで解決しました。

server.xml("0.0.0.0"に修正)
    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector protocol="AJP/1.3"
               address="0.0.0.0"
               port="8009"
               redirectPort="8443" />

はまったこと2

上記「はまったこと1」を対処した後Tomcatを再起動したら、次はこんなログが出力されました。

Tomcat起動時のログ2
    org.apache.catalina.LifecycleException: Protocol handler start failed
        at org.apache.catalina.connector.Connector.startInternal(Connector.java:1066)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardService.startInternal(StandardService.java:438)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:343)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:474)
    Caused by: java.lang.IllegalArgumentException: The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.
        at org.apache.coyote.ajp.AbstractAjpProtocol.start(AbstractAjpProtocol.java:264)
        at org.apache.catalina.connector.Connector.startInternal(Connector.java:1063)
        ... 12 more

調べてみると、server.xml の Connector の属性にsecretRequiredというものがあり、これがデフォルトtrueになっている。trueの場合、secretという属性で合言葉的なものを指定する必要があるらしい。(公式サイト
このサイトでは、「secretRequired="false"」を明示的に指定して解決していたのでこれを真似してみたら解決しました。

server.xml(secretRequired追加)
    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector protocol="AJP/1.3"
               address="0.0.0.0"
               port="8009"
               redirectPort="8443"
               secretRequired="false" />

これでTomcatの設定は完了です。

warのデプロイ

最後に、自分のローカルPCで作成したwarファイルをレンタルサーバにデプロイします。warファイルを/opt/apache-tomcat-9.0.34/webappsに格納すると、Tomcatが自動でデプロイしてくれます。
デプロイが完了したらアクセスしてHello Worldが出ることを確認して終わりです。

以上。

参考

40
44
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
44