HerokuでJavaアプリを公開する手順

備忘録として纏めてみた。多分これより簡単に公開する方法はないと思う。開発環境は下記↓

  • macOS Catalina 10.15.7
  • IntelliJ IDEA Ultimate 2020.3
  • Amazon Corretto 11.0.9
  • Apache Tomcat 9.0.41
  • Apache Maven 3.6.3
  • Gradle 6.7.1
  • Hibernate 5.4.11 Final
  • MySQL 15.1 (MariaDB 10.5.6)

先ずHerokuとはPaaS(Platform as a Service)と呼ばれるサービスでサーバコンピュータを提供している。無料のプランもあるので気軽に公開できる。

@TOC

Herokuでデプロイする手順

-> 開発環境を整える

1. Heroku CLIツールをインストール

% brew install heroku/brew/heroku

Macの場合はHomebrewでインストールする方が簡単。

2. デプロイツールをインストール

% heroku plugins:install heroku-cli-deploy

-> デプロイまで

1. データベースをダンプ

 ~ % cd /Users/kiki/project/tipswatch

cdコマンドでプロジェクトのルートディレクトリに移動。

tipswatch % mysqldump -u root -p tipswatch > tipswatch_dump.sql

mysqldumpコマンドでデータベースをダンプする。ダンプとはデータベースを出力(バックアップ)することね。

2. Herokuへログイン

% heroku login -i
heroku: Enter your login credentials
Email [oo@kiki.ooo]: oo@kiki.ooo
Password: ************************************************************************
Logged in as oo@kiki.ooo

heroku login -iコマンドでログイン。メールアドレスとパスワードの入力を求められる。

3. Herokuでのアプリ名を決める

% heroku create tipswatch
Creating ⬢ tipswatch... done
https://tipswatch.herokuapp.com/ | https://git.heroku.com/tipswatch.git

heroku createコマンドの後にHeroku上に自分のアプリケーション用の領域を名前をつけて確保する。基本的にアプリと同じ名前でいいと思う。ただし、他のユーザが付けた名前とは被ってはいけない。Herokuのダッシュボードからも可能だがCLIでやった方が早い。

4. サーバインスタンスのタイムゾーンを設定

% heroku config:add TZ=Asia/Tokyo --app tipswatch
Setting TZ and restarting ⬢ tipswatch... done, v3
TZ: Asia/Tokyo
  • Herokuサーバ(Dyno)のインスタンスの日付時刻は、グリニッジ標準時に設定されている
    • タイムゾーンの設定を追加して日本時間に合わせる
  • 下のコマンドを実行してJSTになっていればOK
  • --appオプションの後ろにさっき付けたアプリ名
% heroku run date --app tipswatch
Running date on ⬢ tipswatch... up, run.9751 (Free)
Thu Dec 10 19:30:50 JST 2020

5. MySQL(ClearDB)を設定

課金しなくてもカード情報を登録しておくだけで稼働時間が加算されるので迷わず登録。登録が終われば下記コマンドを実行しデータベースを作成する。

% heroku addons:create cleardb:ignite --app tipswatch
Creating cleardb:ignite on ⬢ tipswatch... free
Created cleardb-spherical-27176 as CLEARDB_DATABASE_URL
Use heroku addons:docs cleardb to view documentation

6. データベースのURLを確認

% heroku config --app tipswatch | grep CLEARDB_DATABASE_URL
CLEARDB_DATABASE_URL: mysql://b8861dd7d51e58:********@us-cdbr-east-02.cleardb.com/heroku_7f8850c6ba4f87c?reconnect=true

grepコマンドでデータベースのURLを確認する。URLは以下の構成になっている。

mysql://(ユーザ名):(パスワード)@(ドメイン)/(データベース名)?reconnect=true

7. UTF-8の文字コードを追加

% heroku config:add CLEARDB_DATABASE_URL='mysql://b8861dd7d51e58:********@us-cdbr-east-02.cleardb.com/heroku_7f8850c6ba4f87c?reconnect=true&useSSL=false&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8' --app tipswatch
Setting CLEARDB_DATABASE_URL and restarting ⬢ tipswatch... done, v6
CLEARDB_DATABASE_URL: mysql://b8861dd7d51e58:********@us-cdbr-east-02.cleardb.com/heroku_7f8850c6ba4f87c?reconnect=true&useSSL=false&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
  • UTF-8の文字コードでMySQLを利用する設定
  • 文字コードとは別に&useSSL=falseを追加
    • エラーの発生を防止
  • 設定が正しく反映されているかconfigコマンドで確認
    • 間違っているとMySQLに接続ができないので慎重に
% heroku config --app tipswatch
=== tipswatch Config Vars
CLEARDB_DATABASE_URL: mysql://b8861dd7d51e58:********@us-cdbr-east-02.cleardb.com/heroku_7f8850c6ba4f87c?reconnect=true&useSSL=false&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
TZ:                   Asia/Tokyo

8. persistence.xmlの設定を変更

<properties>
    <property name="javax.persistence.jdbc.user" value="b8861dd7d51e58"/>
    <property name="javax.persistence.jdbc.password" value="********"/>
    <property name="javax.persistence.schema-generation.database.action" value="none"/>
    <property name="javax.persistence.schema-generation.scripts.action" value="none"/>
    <property name="javax.persistence.jdbc.url" value="jdbc:mysql://us-cdbr-east-02.cleardb.com/heroku_7f8850c6ba4f87c?reconnect=true&useSSL=false&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8"/>
</properties>

persistance.xmlの上記項目のみ変更。URLがややこしいので注意が必要。スキーマ生成は下記リンク先を参照。

9. HerokuのMySQLでテーブル生成

% mysql -h us-cdbr-east-02.cleardb.com -u b8861dd7d51e58 -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 94783042
Server version: 5.5.62-log MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysqlコマンドでログイン。-hオプションの後ろはドメイン名、-uオプションの後ろはユーザ名。

MySQL [(none)]> use heroku_7f8850c6ba4f87c;
No connection. Trying to reconnect...
Connection id:    94793168
Current database: *** NONE ***

Database changed

useコマンドでHerokuのデータベース名を指定。

MySQL [heroku_7f8850c6ba4f87c]> source /Users/kiki/project/tipswatch/tipswatch_dump.sql
Query OK, 0 rows affected (0.195 sec)

Query OK, 0 rows affected (0.194 sec)

Query OK, 0 rows affected (0.200 sec)

Query OK, 0 rows affected (0.195 sec)

Query OK, 0 rows affected (0.202 sec)
  • ターミナルでMySQLにログインしなおした上で、さっきダンプしたtipswatch_dump.sqlを実行
    • sqlファイルの絶対パスを控えておく
  • sourceコマンドを実行した後に、Tomcatを再起動するとHerokuのMySQLとアプリが繋がっているはず
    • 次にこの状態でメッセージを1件新規登録できたらデプロイ可能
    • 上記コマンドで一応確かめた
MySQL [heroku_7f8850c6ba4f87c]> show databases;
+------------------------+
| Database               |
+------------------------+
| information_schema     |
| heroku_7f8850c6ba4f87c |
+------------------------+
2 rows in set (4.748 sec)

MySQL [heroku_7f8850c6ba4f87c]> show tables;
+----------------------------------+
| Tables_in_heroku_7f8850c6ba4f87c |
+----------------------------------+
| favors                           |
| follows                          |
| ideas                            |
| joins                            |
| members                          |
| reviews                          |
+----------------------------------+
6 rows in set (0.227 sec)

MySQL [heroku_7f8850c6ba4f87c]> select * from members;
+----+------+------------+------------------------------------------------------------------+------+------------+---------------------+---------------------+
| id | code | name       | password                                                         | role | deleteFlag | createdAt           | updatedAt           |
+----+------+------------+------------------------------------------------------------------+------+------------+---------------------+---------------------+
|  1 | 1    | Damian     | 51F038D5F7283396BA9BC6226040F7CDC0DF29092B28B80C436EB03AEA7381EB |    3 |          0 | 2020-12-09 14:27:16 | 2020-12-09 15:01:24 |
|  2 | 2    | Chris      | 9E6D76AB168F9272491A2AA3C05FEA87884415BA593B8F3A5C3CA8F08AC0C325 |    2 |          0 | 2020-12-09 15:15:20 | 2020-12-09 15:15:20 |
|  3 | 3    | Irving     | 682CF1DBC2BE9754CC47FDCCB1B5DA51282DE5CAA12FCE613942E396E28E75F3 |    1 |          0 | 2020-12-09 15:15:37 | 2020-12-09 15:15:37 |
|  4 | 4    | Lindsay    | C1C998EBA318A7CA6A8B05E1002DFDDE867CB41A58199DA80AE064F9702A685E |    0 |          0 | 2020-12-09 15:15:51 | 2020-12-09 15:15:51 |
|  5 | 5    | Mona       | 20DCA2B7D2B7820FC8671B036C63E9C70246655BA0DD48B511CCF07E75C619DD |    3 |          0 | 2020-12-09 15:16:10 | 2020-12-09 15:16:10 |
|  6 | 6    | Margaretha | F37B53DCAC13A3CC4FBB15BB600BFF04C0CEED6F450AD72B051453A91ADD6016 |    2 |          0 | 2020-12-09 15:16:29 | 2020-12-09 15:16:29 |
|  7 | 7    | Leone      | FC7C61541A688E8261B947B5C4E22BB7B91DAD3388B726D2190DEDFB9B3FB4C1 |    1 |          0 | 2020-12-09 15:16:52 | 2020-12-09 15:16:52 |
|  8 | 8    | Nora       | 7DB84286C4B197C677DE247DE73F89E65D4B873CE12C34FA683E00A1C351DADB |    0 |          0 | 2020-12-09 15:17:05 | 2020-12-09 15:17:05 |
|  9 | 9    | Christian  | 912E30234212857814312F4A1E9D4108E0D00D969FB6502C8F8398824DA25AA5 |    0 |          0 | 2020-12-09 15:17:19 | 2020-12-09 15:17:19 |
| 10 | 10   | Corrie     | C5DD9173A589EE432C1C9197B1553F3CE854F25186334378A483D2E86B3FCDC3 |    0 |          0 | 2020-12-09 15:17:31 | 2020-12-09 15:17:31 |
| 11 | 11   | Bianca     | 58EA85A85C01B9537B77EAF24DCAFC159742F5E6048096B74527D8B4BC6883A3 |    0 |          0 | 2020-12-09 15:17:41 | 2020-12-09 15:17:41 |
| 12 | 12   | Florence   | CF3D851A238E42E6025F2C9E78B85807EF66D6C9C303EE204B5CFED643607160 |    0 |          0 | 2020-12-09 15:17:53 | 2020-12-09 15:17:53 |
| 13 | 13   | Carlie     | 8C35E854DF8A6A39D5D749C4375D38C743BC0FFAF027CA539F9BC6603F57B9A9 |    0 |          0 | 2020-12-09 15:18:02 | 2020-12-09 15:18:02 |
| 14 | 14   | Eugenia    | 3C09F75CE065D684C730AF144609C62F5A8B925CA278920FD98E7E813F095CE1 |    0 |          0 | 2020-12-09 15:18:12 | 2020-12-09 15:18:12 |
| 15 | 15   | Kathleen   | 11F51A1FFE0EBBCB6CD9A5115B1201AA4B77F63A127DA9F7629A0F2EC33594BF |    0 |          0 | 2020-12-09 15:18:23 | 2020-12-09 15:18:23 |
| 16 | 16   | Carina     | 1FFF178072125A4F8DC6DD64D9C14A5A4B056849C8ECFFE73D1B6C97EF843966 |    0 |          0 | 2020-12-09 15:18:40 | 2020-12-09 15:18:40 |
| 17 | 17   | Madeline   | B69CBF9FF084CD7B6C10E5A2F75DEC35E98EE04E7C4439A2B19A24CD31DEE9BA |    0 |          0 | 2020-12-09 15:18:51 | 2020-12-09 15:18:51 |
| 18 | 18   | Juliet     | 409C80226C448F9E08AA77EBA29A7A3012ECA6D883E7DE14DA8A7A3510C47120 |    0 |          0 | 2020-12-09 15:19:02 | 2020-12-09 15:19:02 |
| 19 | 19   | Ann        | E91392D477D959108EE9535A33D2F0A6220A54AECBD1363A046AE81487052434 |    0 |          0 | 2020-12-09 15:19:14 | 2020-12-09 15:19:14 |
| 20 | 20   | Alexia     | 93124AC217328E6ECEBF4215AB20CD79860A13A60C587275A298A7FC6B1E4343 |    0 |          0 | 2020-12-09 15:19:32 | 2020-12-09 15:19:32 |
| 21 | 21   | Helen      | 877DE3B76BCD8439BC1E1AC969BA5A2E14CDE8B02BE0FD23495DFA5B602AB8CF |    0 |          0 | 2020-12-09 15:19:43 | 2020-12-09 15:19:43 |
| 22 | 22   | Dianna     | 0D898395747A443DF69F8D977742699544BDAA5A2CA8BFA3A8AB8DD52884630B |    0 |          0 | 2020-12-09 15:20:05 | 2020-12-09 15:20:05 |
| 23 | 23   | May        | 33E36C3CC370B9A50B82478C2FF0F555DA5CF7A160282132098B61AACDC57C9A |    0 |          0 | 2020-12-09 15:20:17 | 2020-12-09 15:20:17 |
| 24 | 24   | Nathalia   | B2D22D4E4B9EE6A4BCAF4BFDCEF8D820935733D63DE44BFF1DC1622DC5CCA21F |    0 |          0 | 2020-12-09 15:20:29 | 2020-12-09 15:20:29 |
+----+------+------------+------------------------------------------------------------------+------+------------+---------------------+---------------------+
24 rows in set (0.217 sec)

この段階で500エラーが発生した。エラー文を見るとエンティティが正しく読み込まれていないようだった。心当たりがあるのはLombok。以下に解決方法を纏めた↓

今回は纏めなかったがio.freefair.lombokを入れると問題は解消された。が、色々あって結局Mavenに戻した……。

10. パスを通しておく

環境構築した時にパスは通しているはずだが一応確認しておく。

% vi ~/.bash_profile

Vimで.bash_profileを開く。

export PATH=$PATH:/usr/local/mysql/bin:/Users/kiki/Library/Java/JavaVirtualMachines/corretto-11.0.9.1/Contents/Home/bin
export JAVA_HOME=/Users/kiki/Library/Java/JavaVirtualMachines/corretto-11.0.9.1/Contents/Home/

環境変数を設定。使っているJDKによってパスは異なるので要注意。私の場合は上記のようになった(Amazon Corretto 11)。IntelliJでインストールしたら多分このようなパスになる。Eclipse(Pleiades All in One)だとアプリの中にある。

11. WARファイルをHerokuにデプロイ

Eclipseで新たに生成しても良いし、IntelliJでパスを辿っても良い。今回はIntelliJのパスを辿ってwarファイルを探し出した。下記のコマンドでHerokuにデプロイ↓

% HEROKU_DEBUG=1 heroku war:deploy /Users/kiki/project/tipswatch/target/tipswatch-0.0.1-SNAPSHOT.war --app tipswatch --webapp-runner 8.0.50.0
java -Dheroku.appName=tipswatch -Xmx1g -Dheroku.webappRunnerVersion=8.0.50.0 -Dheroku.warFile=/Users/kiki/project/tipswatch/target/tipswatch-0.0.1-SNAPSHOT.war -jar /Users/kiki/.local/share/heroku/node_modules/@heroku-cli/plugin-java/lib/heroku-deploy-complete.jar
-----> Packaging application...
       - app: tipswatch
       - including: webapp-runner.jar
       - including: tipswatch.war
Procfile:
===================
web: java $JAVA_OPTS -jar webapp-runner.jar ${WEBAPP_RUNNER_OPTS} --port $PORT ./tipswatch.war

===================
Heroku existing config variables: [CLEARDB_DATABASE_URL, TZ]
-----> Creating build...
       - file: slug.tgz
       - size: 23MB
Heroku Blob URL: https://s3-external-1.amazonaws.com/heroku-sources-production/4c0616e2-a8b6-4f71-b08a-baedf0b2fa5a?AWSAccessKeyId=AKIAJ6LKZGKGPARPZE4A&Signature=vBo7x6XzyU7LJwuBrVrso4D11F0%3D&Expires=1607763333
-----> Uploading build...
       - success
-----> Deploying...
remote:
remote: -----> heroku-deploy app detected
remote: -----> Installing JDK 1.8... done
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing...
remote:        Done: 75.7M
remote: -----> Launching...
remote:        Released v9
remote:        https://tipswatch.herokuapp.com/ deployed to Heroku
remote:
-----> Done

--webapp-runnerというオプションを使ってみた。詳細はGitHubにあるので参照されたし。

が、ログをよく見てみると何故かJDKのバーションが1.8(Java 8)になっている。調べてみるとデフォルトではそうなるようだ。なので変更する手順が必要になる。幸いJava 11には対応していた。

※ Heroku Java CLI plugin をインストール

% heroku plugins:install java
Installing plugin java... installed v3.1.1

※ バージョンを明示的に指定

プロジェクト直下にsystem.propertiesという名前のファイルを作成する。そこに下記のように明示的にJavaのバージョンを指定。

java.runtime.version=11

この状態で再びデプロイしてみると……。

% HEROKU_DEBUG=1 heroku war:deploy /Users/kiki/project/tipswatch/target/tipswatch-0.0.1-SNAPSHOT.war --app tipswatch --webapp-runner 8.0.50.0
Uploading tipswatch.war
java -Dheroku.appName=tipswatch -Xmx1g -Dheroku.webappRunnerVersion=8.0.50.0 -Dheroku.warFile=/Users/kiki/project/tipswatch/target/tipswatch-0.0.1-SNAPSHOT.war -jar /Users/kiki/.local/share/heroku/node_modules/@heroku-cli/plugin-java/lib/heroku-deploy-complete.jar
-----> Packaging application...
       - app: tipswatch
       - including: webapp-runner.jar
       - including: tipswatch.war
Procfile:
===================
web: java $JAVA_OPTS -jar webapp-runner.jar ${WEBAPP_RUNNER_OPTS} --port $PORT ./tipswatch.war

===================
Heroku existing config variables: [CLEARDB_DATABASE_URL, TZ]
-----> Creating build...
       - file: slug.tgz
       - size: 23MB
Heroku Blob URL: https://s3-external-1.amazonaws.com/heroku-sources-production/30d17140-1988-4806-9eb1-a541b3fb6beb?AWSAccessKeyId=AKIAJ6LKZGKGPARPZE4A&Signature=4ytijKRy%2BN5Axf4VfSNTIAL95J8%3D&Expires=1607774033
-----> Uploading build...
       - success
-----> Deploying...
remote:
remote: -----> heroku-deploy app detected
remote: -----> Installing JDK 11... done
remote: -----> Discovering process types
remote:        Procfile declares types -> web
remote:
remote: -----> Compressing...
remote:        Done: 83.2M
remote: -----> Launching...
remote:        Released v10
remote:        https://tipswatch.herokuapp.com/ deployed to Heroku
remote:
-----> Done

ちゃんとJDK 11がインストールされた。対象のURLにアクセスするとちゃんと表示された。悪戯されたら嫌だからここにはURLを載せないけどこの一連の流れを見ている人であれば大体見当がつくと思う。これでHerokuのデプロイは終了。めっちゃ簡単だった。後はパイプラインとか通してみるかな。

To comment

@TOC
閉じる