独り言

プログラミングの講師をしています。新人研修で扱う技術の解説と個人の技術メモ、技術書の紹介など

【Java】【AWS】Amazon EC2でJavaのWebアプリケーション動作環境を構築してデプロイするまで

クラウド上にJavaによるWebアプリケーションの動作環境を構築する手順です。
AWSAmazon EC2を使用し、マシンイメージはAmazon Linux 2 を利用します。
DBはPostgreSQLを使用する前提とします。

解説する内容は以下の項目。
インスタンスの作成までに関する手順とSSH接続する手順は省略します。

  • ロケールの変更
  • PostgreSQLのインストール
  • Javaのインストール
  • ApacheTomcatのインストール
  • GitとMavenのインストール
  • Webアプリケーションのデプロイ
  • Gitを活用したデプロイ方法

ロケールの変更

参考サイト
Amazon LinuxのデフォルトのロケールはENになっている。
Spring Bootをでメッセージリソースを使う場合、デフォルトでen用のファイルを読み込んでしまう。
ファイルがない場合はエラーになるので、日本に設定しておく。

# ロケールの確認
$ localectl status
# ロケール変更
localectl set-locale LANG=ja_JP.eucjp
# 変更されたか確認
$ localectl status

PostgreSQLのインストール

ここではEC2インスタンスPostgreSQLをインストールして外部から接続できるようにする手順を解説します。
該当のEC2インスタンスSSH接続されていることを前提とします。

参考サイト

1. リポジトリの更新

まずはリポジトリを更新する。 デフォルトの状態でPosgreSQLをインストールするとバージョンが9.2なので(2020/09時点)最新バージョンがインストールできるようにリポジトリ更新します。

$ wget https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
$ sudo rpm -Uvh --nodeps pgdg-redhat-repo-latest.noarch.rpm
$ sudo sed --in-place -e "s/\$releasever/7/g" /etc/yum.repos.d/pgdg-redhat-all.repo

2.PostgreSQLのインストールと環境設定

まずはインストールしてサービスの起動

# postgreSQLのインストール
$ sudo yum -y install postgresql12-server
# データベース初期化
$ sudo /usr/pgsql-12/bin/postgresql-12-setup initdb
# サービス自動起動設定
$ sudo systemctl enable postgresql-12
# サービスの起動
$ sudo systemctl start postgresql-12.service

デフォルトではOSユーザーでログインする設定なので、postgresユーザーにパスワードを与えてログインする。
(PostgreSQLをインストールすると自動でpostgresユーザーが作成される)

# postgresのパスワード変更(ここではpasswordとする)
$ sudo passwd postgres
⇒password

# ユーザーを切り替え
$ su - postgres
password ⇒ password

# postgreSQLへログイン
$ psql

PostgreSQL内のpostgresユーザーのパスワードを変更しておく。
デフォルトだとパスワードは設定されていない。

# postgreSQL内のpostgreユーザーのパスワード変更(ここではpasswordとする)
alter user postgres with password 'password';

# postgresqlログアウト
\q

postgresqlからログアウトしてec2-userに戻ったら、外部からOSのユーザー以外でもログインできるように設定ファイルを変更する。

# ec2-userに戻る(postgreユーザーになっているため)
$ exit

# 設定ファイルの変更
# 外部からのアクセスできるようにする
$ sudo vi /var/lib/pgsql/12/data/postgresql.conf

# listen_address = 'localhost'
⇓
listen_address = '*'

# 設定ファイルの変更
# 外部からのpostgreSQLユーザーのパスワードでアクセスできるようにする
$ sudo vi /var/lib/pgsql/12/data/pg_hba.conf

# IPv4 local conecctions:
host  all  all  127.0.0.1/32  ident
⇓
host  all  all  0.0.0.0/0  md5

# サービス再起動
$ sudo systemctl restart postgresql-12.service

外部からの接続を確認する。
コマンドプロンプトpowershell等から

psql -h <パブリックDNS> -p 5432 -U postgres -d postgres

その後パスワード(ここではpassword)を入力して接続できることを確認する。


Javaのインストール

Java環境のインストール方法です。
AmazonのOpenJDK(amazon-corretto)をインストールします。

参考サイト

# JDKインストール
$ sudo yum -y install java-11-amazon-corretto
# javac バージョン確認
$ javac --version
# java バージョン確認
$ java --version

ApacheTomcatのインストール

ApacheTomcatのインストールに関しては以下のサイトを参考に。
参考サイト

ちなみに、Spring Bootアプリケーションをデプロイする場合はビルドされたファイルにTomcatが含まれるため、全グループがSpring Bootアプリケーションを前提に開発を進める場合はこの手順は省略しても問題ありません。

Apacheインストール

# インストール
$ sudo yum install -y httpd
# 確認
$ httpd -v
# 自動起動設定
$ sudo systemctl enable httpd.service
# 起動
$ sudo systemctl start httpd.service
# 停止
$ sudo systemctl stop httpd.service

Tomcatインストール

ダウンロードするバージョンは
公式サイト
から確認

# ユーザー作成
$ sudo useradd -s /sbin/nologin tomcat

# tomcatダウンロード
$ cd ~
$ wget https://downloads.apache.org/tomcat/tomcat-9/v9.0.38/bin/apache-tomcat-9.0.38.tar.gz

# 解凍して配置
$ tar -xzvf ~/apache-tomcat-9.0.38.tar.gz
$ sudo mv ~/apache-tomcat-9.0.38 /opt
$ sudo chown -R tomcat:tomcat /opt/apache-tomcat-9.0.38

# シンボリックリンクの作成
$ sudo ln -s /opt/apache-tomcat-9.0.38 /opt/apache-tomcat
$ sudo chown -h tomcat:tomcat /opt/apache-tomcat

# ログのシンボリックリンク作成
$ sudo ln -s /opt/apache-tomcat/logs /var/log/tomcat
$ sudo chown -h tomcat:tomcat /var/log/tomcat

# TomcatをOSにサービスとして登録する為、ルート権限でUnitを作成
$ sudo vi /usr/lib/systemd/system/tomcat.service

tomcat.service

[Unit]
Description=Apache Tomcat Web Application Container
After=syslog.target network.target

[Service]
Type=oneshot
PIDFile=/opt/apache-tomcat/tomcat.pid
RemainAfterExit=yes
#EnvironmentFile=/etc/tomcat/tomcat.conf
#Environment="NAME="
#EnvironmentFile=-/etc/sysconfig/tomcat
ExecStart=/opt/apache-tomcat/bin/startup.sh
ExecStop=/opt/apache-tomcat/bin/shutdown.sh
ExecReStart=/opt/apache-tomcat/bin/shutdown.sh;/opt/apache-tomcat/bin/startup.sh
SuccessExitStatus=143
User=tomcat
Group=tomcat

[Install]
WantedBy=multi-user.target
# 自動起動設定
$ sudo systemctl enable tomcat.service
# システム起動
# Apacheを先に起動
$ sudo systemctl start httpd.service
$ sudo systemctl start tomcat.service

# システム停止
$ sudo systemctl stop tomcat.service

ブラウザから http://<パブリックDNS>:8080 でTomcatのトップページにアクセスできることを確認する。


http://ec2-18-182-18-43.ap-northeast-1.compute.amazonaws.com:8080/

※Spring Bootアプリケーションを起動したい場合は、Tomcatが起動しているとポート番号が重複してエラーになるので注意。


GitとMavenのインストール

GitとMavenを使ってデプロイすることも可能なので、それ用にインストールしておいても良いかも

Gitのインストール

# git インストール
$ sudo yum -y install git 
# バージョン確認
$ git version

Mavenのインストール

参考サイト

mavenの最新バージョンのリンクはこちらから

# ダウンロード
$ cd ~
$ sudo wget https://ftp.jaist.ac.jp/pub/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz

# 展開&配置
$ sudo tar -xzvf apache-maven-3.6.3-bin.tar.gz
$ sudo mv apache-maven-3.6.3 /opt/
# シンボリックリンク作成
$ sudo ln -s /opt/apache-maven-3.6.3 /opt/apache-maven
# PATHの追加
$ vi .bash_profile
PATH=$PATH:$HOME/.local/bin:$HOME/bin
⇓
MVN_HOME=/opt/apache-maven
PATH=$MVN_HOME/bin:$PATH:$HOME/.local/bin:$HOME/bin
# PATHを通す
$ source .bash_profile
# Mavenバージョン確認
$ mvn --version

Webアプリケーションのデプロイ方法

デプロイとは開発環境のプログラムをアプリケーションを動作させる本番環境に反映させることをいいます。

Spring Bootを使用した場合と使用しない場合で方法が異なります。

Spring Bootアプリケーションの場合(JSPを使用していない場合)

参考サイト

プロジェクトをビルドしてjarファイルを作成する
Eclipseで対象のSpring Bootプロジェクトを右クリック ⇒ 実行 ⇒ Maven install を実行。
ビルドが成功したらtarget配下にjarファイルができる。

※環境によってはエラーが出ることがある。

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test

その時はsrc/test/java配下にあるテストクラスにある@SpringBootTestアノテーションに引数を追加する。

// クラス名は@SpringBootApplicationがついているクラス
@SpringBootTest(classes = {TaskFrameworkApplication.class})

これでエラーが解消する場合がある。

jarファイルを転送する
scpコマンドなどを使用してjarファイルをEC2インスタンスに転送する。

コマンドプロンプトなどから

scp -i pemファイル "jarファイルのパス" ユーザー名@パブリックDNS:転送先のパス

を実行する


デスクトップのjarファイルをec2-userのホームディレクトリに転送する

scp -i nihonbasib_20200915.pem "C:\Users\admin\Desktop\demo-0.0.1-SNAPSHOT.jar" ec2-user@ec2-18-182-18-43.ap-northeast-1.compute.amazonaws.com:~/

Webアプリケーションを実行する EC2インスタンスSSH接続し

java -jar 転送されたjarファイル

を実行するとSpringBootアプリケーションが起動する。

ブラウザからアクセスして動作を確かめる http://パブリックDNS:8080/マッピングしているパス

プログラムを停止したい場合
Ctrl + CでTomcatを停止することができます。
ただしサーバーを停止してもプロセスが残っている場合があります。
その場合はpsコマンドでプロセスIDを確認し、killコマンドで終了させる。

# プロセスの確認
$ ps a
# 出力結果からjavaアプリケーションのPIDを確認
# killコマンドでプロセスを削除
$ kill PID

Spring Bootアプリケーションの場合(JSPを使用している場合)

参考サイト JSPを使用する場合(アプリケーションにWEB-INFフォルダが存在している場合)は、jarファイルによるデプロイができない。
jarファイルとして作成した場合、WEB-INFフォルダが作成されない。
warファイルとして作成し、Tomcat上でデプロイする必要がある。
ビルドの方法は変わらない。

pom.xmlに以下を追加

<packaging>war</packaging>

書く場所はproject要素の直下。
propertiesやdependenciesなどと同じ階層に書く。
Eclipseの場合はプロジェクト作成時にビルドがjarかwarかを選択できるので、そこでwarを選択しておけば勝手に追記されるはず。

また、warファイルでデプロイする場合は外部のTomcatを使ってデプロイするため、warファイルにTomcatを含める必要がなくなる。
デフォルトだとTomcatを含めてしまうので、pom.xmlで省くように設定する。

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
</dependency>

scopeをprovidedにすれば良い。
warファイルのデプロイ方法は次節の動的Webアプリケーションの場合で解説します。

動的Webアプリケーションの場合

Spring Bootを使用せずにJSP/Servletのみで作成した場合
参考サイト

warファイルを作成する Eclipseからプロジェクトを右クリック ⇒ エクスポート ⇒ warファイルを選択。
出力先を指定してwarファイルを出力します。

warファイルを転送する scpコマンドなどでwarファイルをEC2インスタンスに転送します。

scp -i pemファイル "warファイルのパス" ec2-user@パブリックDNS:~/ 

scp -i nihonbasib_20200915.pem "C:\Users\admin\Desktop\demo.war" ec2-user@ec2-18-182-18-43.ap-northeast-1.compute.amazonaws.com:~/

※ユーザー名(ec2-user)を書き忘れるとPermissionのエラーが出る。
パブリックDNSだけコピーして実行しようとするとエラーになるので注意。

Tomcatの起動とwarファイルの展開 EC2インスタンスssh接続し、転送されたwarファイルを
tomcatがインストールされたディレクトリ/webapps
に配置します。
tomcatは /opt/apache-tomcat
にインストールされている想定です。
インストールされていない場合は講師に確認してください。

$ sudo cp warファイル /opt/apache-tomcat/webapps
# Apacheを起動
$ sudo systemctl start httpd.service
# Tomcatを起動
$ sudo systemctl start tomcat.service

Tomcatの起動に成功すれば、webapps配下でwarファイルが展開されます。
展開されているかどうかはlsコマンドなどで確認してください。

$ sudo ls /opt/apache-tomcat/webapps/

ブラウザから http://パブリックDNS:8080/コンテキストルート
でアクセスして実行結果を確認する。


Gitを活用したデプロイ方法

Eclipseからjarファイルやwarファイルを作成してEC2上に転送するのではなく、直接EC2インスタンス上でjarファイルやwarファイルを作成することも可能です。

前提条件
* EC2インスタンスにGitがインストールされていること
* EC2インスタンスMavenがインストールされていること(Spring Bootを使用する場合)
* GitHub, GitLabなどのホスティングサービスにリモートリポジトリが作成されていること ※.gitignoreでクラスファイルなどが除外されていることを確認して下さい。

# Gitがインストールされていることの確認
$ git version

# 初期設定をしておく
# ユーザー名の設定
git config --global user.name "ユーザー名"
# メールアドレスの設定
git config --global user.email "メールアドレス"

# リモートリポジトリをクローンする
$ git clone リモートリポジトリのURL

# 作業ディレクトリ移動
$ cd クローンされたプロジェクト

Spring Bootの場合

プロジェクトのディレクトリ配下にpom.xmlがあることを確認する。
ビルドする際にpom.xmlがないとうまくいかない。

プロジェクトのビルド

# Mavenがインストールされていることの確認
$ mvn --version
# ビルド
$ mvn package spring-boot:repackage

ビルドが成功すればtargetディレクトリが作成され、中にjarファイルが出来上がります。

Webアプリケーションを実行する jarファイルを使ってアプリケーションを起動します。

java -jar 転送されたjarファイル

ブラウザからアクセスして動作を確かめる http://パブリックDNS:8080/マッピングしているパス

プログラムを停止したい場合
Ctrl + CでTomcatを停止することができます。
ただしサーバーを停止してもプロセスが残っている場合があります。
その場合はpsコマンドでプロセスIDを確認し、killコマンドで終了させる。

# プロセスの確認
$ ps a
# 出力結果からjavaアプリケーションのPIDを確認
# killコマンドでプロセスを削除
$ kill PID

動的Webアプリケーションの場合

参考サイト 「src」と「WebContent」ディレクトリがあるディレクトリに移動しておく。

# ライブラリ用ディレクトリ作成
$ mkdir lib
# servlet-api.jarを移動しておく
$ sudo cp /opt/apache-tomcat/lib/servlet-api.jar lib
# ソースファイルをコンパイルする
$ javac -sourcepath src -classpath lib/* -d WebContent/WEB-INF/classes src/example/*

# warファイルを作成
$ jar cvf webtest.war -C WebContent .

Tomcatの起動とwarファイルの展開 warファイルを
tomcatがインストールされたディレクトリ/webapps
に配置します。
tomcatは /opt/apache-tomcat
にインストールされている想定です。
インストールされていない場合は講師に確認してください。

$ sudo cp warファイル /opt/apache-tomcat/webapps
# Apacheを起動
$ sudo systemctl start httpd.service
# Tomcatを起動
$ sudo systemctl start tomcat.service

Tomcatの起動に成功すれば、webapps配下でwarファイルが展開されます。
展開されているかどうかはlsコマンドなどで確認してください。

$ sudo ls /opt/apache-tomcat/webapps/

ブラウザから http://パブリックDNS:8080/コンテキストルート
でアクセスして実行結果を確認する。