はじめに
ポートフォリオの環境構築をGCPで行うことが2度目なので、
今後も行うことを想定して備忘録として全体の流れをまとめておきます。
駄文ですが、部分的でもどなたかのお役に立てれば幸いです。
全体の流れ
Springをwarファイルにビルドしたものを、
GCPで生成したCentOS上にTomcatとmariadbを構築して動かします。
- GCPのインスタンス生成
- Tomcatインストール
- ポートフォワーディングの設定
- mariadbインストール
- タイムゾーンの設定
- セッションタイムアウトの設定
GCPのインスタンス生成
インストールする際の各種設定(無料枠について,os,firewall,ネットワーク等)
userのパスワード変更してsshできるように設定
参考:
(2023年版) Google Cloud 無料枠 ホントに課金されない?の検証
リージョン
を無料枠のオレゴン・アイオワ・サウスカロライナのいずれか選択
ブートディスク
のタイプを無料枠の標準永続ディスクに変更
サイズを無料枠の30GB以下に変更
イメージを無料枠の好きなOSに変更(私はCentOS7にしました)
ファイアウォール
のHTTP,HTTPSトラフィックの許可(80ポートの許可)
詳細オプション
静的外部IPの設定をする場合
TeraTermなどでSSH通信する場合
手動で生成したSSH認証鍵の追加
から項目の追加
を押して、
自分が生成した公開鍵を追加。
JDK17インストール
参考:下記手順をsudoコマンドで実行します。
CentOS 7にOpenJDK 17をインストール(Azul Zulu Builds of OpenJDK)
Tomcatインストール
参考:
Apache Tomcat 9 を CentOS 7 にインストールする手順
Apache Tomcatをインストールしたらすぐに設定したいセキュリティ対策
Tomcat を動かすための専用ユーザとして tomcat を追加します。
# useradd -s /sbin/nologin tomcat
tar.gz 形式の Apache Tomcat 10 本体をダウンロードします。
(現在の最新版は11だが、Webアプリの作成環境が10なのでこちらを使用)
# cd ~
# curl -O http://ftp.riken.jp/net/apache/tomcat/tomcat-10/v10.1.13/bin/apache-tomcat-10.1.13.tar.gz
ダウンロードした tar.gz ファイルを解凍して配置します。
tar コマンドで解凍して、今回は /opt に配置します。
また、解凍した Apache Tomcat の所有者を作成したtomcatユーザの所有とします。
$ tar -xzvf ~/apache-tomcat-10.1.13.tar.gz
$ sudo mv ~/apache-tomcat-10.1.13 /opt
$ sudo chown -R tomcat:tomcat /opt/apache-tomcat-10.1.13
Apache Tomcat 10 をサービスとして登録します。
まずは /etc/systemd/system/tomcat.service を新たに作成して、
つぎのように記述して保存します。
$ sudo vi /etc/systemd/system/tomcat.service
[Unit]
Description=Apache Tomcat 10
After=network.target
[Service]
User=tomcat
Group=tomcat
Type=oneshot
PIDFile=/opt/apache-tomcat-10.1.13/tomcat.pid
RemainAfterExit=yes
ExecStart=/opt/apache-tomcat-10.1.13/bin/startup.sh
ExecStop=/opt/apache-tomcat-10.1.13/bin/shutdown.sh
ExecReStart=/opt/apache-tomcat-10.1.13/bin/shutdown.sh;/opt/apache-tomcat-10.1.13/bin/startup.sh
[Install]
WantedBy=multi-user.target
作成した定義ファイルの権限を 755 に変更。
$ sudo chmod 755 /etc/systemd/system/tomcat.service
定義ファイルの作成が完了したら、
systemctl enable コマンドでサービスを有効にします。
$ sudo systemctl enable tomcat
Apache Tomcat 10 を起動してみます。
Active: active
と表示されたらOK。
$ sudo systemctl start tomcat
$ sudo systemctl status tomcat
● tomcat.service - Apache Tomcat 10
Loaded: loaded (/etc/systemd/system/tomcat.service; enabled; vendor preset: disabled)
Active: active (exited)
firewalledの設定のため、一度stopさせます。
$ sudo systemctl stop tomcat
Firewalldで8080番を有効に設定します。
/etc/firewalld/services/ フォルダに tomcat.xml を作成します。
$ sudo vi /etc/firewalld/services/tomcat.xml
//下記内容をコピペ
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>Apache Tomcat 10</short>
<description>Apache Tomcat 10</description>
<port protocol="tcp" port="8080"/>
</service>
Firewalld が現時点で通信を許可しているサービスは、firewall-cmd
コマンドで確認できます。
確認するとdhcpv6-client と ssh のサービスが許可されていることが分かります。
$ sudo firewall-cmd --list-services --zone=public --permanent
dhcpv6-client ssh
tomcat の通信を許可するように、次のように firewall-cmd を実行します。
$ sudo firewall-cmd --add-service=tomcat --zone=public --permanent
$ sudo firewall-cmd --reload
もう一度、現在通信を許可しているサービスを確認すると、
今度は tomcat が追加されたことが確認できます。
$ sudo firewall-cmd --list-services --zone=public --permanent
dhcpv6-client ssh tomcat
以下はやらなくても可。
GET と POST 以外のメソッドを拒否する設定をします。
Tomcatのホームディレクトリ配下の conf/web.xml (特定のアプリケーションだけ設定したい場合は、アプリケーション内のweb.xml)に<http-method>
タグで拒否したいメソッドを列挙します。
## 以下をコピペ
<security-constraint>
<web-resource-collection>
<web-resource-name>deny method</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>HEAD</http-method>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
<http-method>CONNECT</http-method>
<http-method>PATCH</http-method>
<http-method>PROPFIND</http-method>
<http-method>PROPPATCH</http-method>
<http-method>MKCOL</http-method>
<http-method>COPY</http-method>
<http-method>MOVE</http-method>
<http-method>LOCK</http-method>
<http-method>UNLOCK</http-method>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
apatch-tomcat/webapps
にwarファイルを配置します。
tomcatにリスタートをかけます。
$ sudo systemctl restart tomcat
アクセスできたら完了です。
ポートフォワーディングの設定
私の環境だとTomcatを80番ポートに設定できないので、
ポートフォワーディングで疑似的に80番ポートのアクセスを受け付けます。
80番ポートのアクセスを8080番に転送しています。
$ sudo firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080
#設定の永久化
$ sudo firewall-cmd --runtime-to-permanent
これでIPアドレスやドメインから直接サインインすることが可能になりました。
mariadb
参考:
初心者向け CentOS7.9 に MariaDB 10.6をインストール
Download MariaDB Server(公式)
公式の手順に従って行います。
まずRepositoryを作ります。
$ sudo vi /etc/yum.repos.d/MariaDB.repo
#以下内容コピペ
# MariaDB 11.1 CentOS repository list - created 2023-08-29 12:25 UTC
# https://mariadb.org/download/
[mariadb]
name = MariaDB
# rpm.mariadb.org is a dynamic mirror if your preferred mirror goes offline. See https://mariadb.org/mirrorbits/ for details.
# baseurl = https://rpm.mariadb.org/11.1/centos/$releasever/$basearch
baseurl = https://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb/yum/11.1/centos/$releasever/$basearch
module_hotfixes = 1
# gpgkey = https://rpm.mariadb.org/RPM-GPG-KEY-MariaDB
gpgkey = https://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb/yum/RPM-GPG-KEY-MariaDB
gpgcheck = 1
mariadbのインストールを実行します。
$ sudo yum install MariaDB-server MariaDB-client
#ひたすらyを押して、以下が出たら完了
Replaced:
mariadb-libs.x86_64 1:5.5.68-1.el7
Complete!
mariadbを実行します。
$ sudo systemctl enable mariadb
$ sudo systemctl start mariadb
$ sudo systemctl status mariadb
#以下表示ならOK
Active: active (running)
mariadbの最低限の設定を行います。
$ sudo mariadb -u root -p
Enter password: #そのままEnterキーを押す
#パスワードを設定
mariaDB[(none)]> ALTER USER 'root'@'localhost' IDENTIFIED BY "ここにパスワードを設定";
この後はWebアプリで使用するデータベースを構築するだけです。
タイムゾーンの設定
参考:
タイムゾーンを日本標準時(JST)に変更する CentOS 8, 7
私の作成したWebアプリでは日時を表示する機能があります。
そのため、Linuxのタイムゾーンを東京に変えます。
timedatectlコマンドでタイムゾーンを東京に設定します。
$ sudo timedatectl set-timezone Asia/Tokyo
$ sudo timedatectl status
#以下が出力される
Local time: Wed 2023-08-30 16:30:52 JST
Universal time: Wed 2023-08-30 07:30:52 UTC
RTC time: Wed 2023-08-30 07:30:52
Time zone: Asia/Tokyo (JST, +0900)
NTP enabled: yes
NTP synchronized: yes
RTC in local TZ: no
DST active: n/a
mariadbを再起動してタイムゾーンを更新します。
$ sudo systemctl restart mariadb
$ mariadb -u root -p
MariaDB [(none)]> select @@time_zone; select @@system_time_zone;
+-------------+
| @@time_zone |
+-------------+
| SYSTEM |
+-------------+
1 row in set (0.000 sec)
+--------------------+
| @@system_time_zone |
+--------------------+
| JST |
+--------------------+
1 row in set (0.000 sec)
JSTに変更できました。
余談
500エラーの事例
Webアプリを動かすと500エラーが発生したので事例を載せておきます。
そもそもどこのログを見たら良いか
500エラーが発生した場合、エラーページでは詳細が分かりません。 Tomcatでは`apache-tomcat/logs/catalina.out`で分かります。小文字、大文字の統一
org.springframework.jdbc.BadSqlGrammarException:
PreparedStatementCallback; bad SQL grammar [SELECT NAME FROM USER WHERE NAME = ?]
...
Caused by: java.sql.SQLSyntaxErrorException:
(conn=31) Table 'learning_stopwatch.USER' doesn't exist
データベースの全ての定義を小文字
で行っているにも関わらず、
JavaのSQL文に一部、大文字
で指示している部分がありました。
小文字
に修正すれば動きました。
文字コード
参考:
文字コードに関する設定を記述する
MySQLのテーブル作成後に、文字コードをutf8mb4に変更する
o.m.jdbc.message.server.ErrorPacket:
Error:1366-22007:Incorrect string value:'\xE5\xAE\x8C\xE6\x88\x90...' for column
insert intoした文字列が、
サポートする文字コードと合わない場合に表示されるエラーのようです。
mariadbの文字コードを確認してみます。
MariaDB [(none)]> SHOW VARIABLES LIKE 'chara%';
+--------------------------+------------------------------+
| Variable_name | Value |
+--------------------------+------------------------------+
| character_set_client | utf8mb3 |
| character_set_connection | utf8mb3 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8mb3 |
| character_set_server | latin1 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mariadb/charsets/ |
+--------------------------+------------------------------+
クライアントに関係する部分は以下の3つのようです。
全てutf8なので問題なさそうです。
character_set_client
クライアントからSQL文などが送信される時に使用される文字コード
character_set_connection
クライアント側から受け取った文字を変換する文字コード
character_set_results
クライアントへ結果を送信する時に使用される文字コード
続いて、データベースとテーブルの文字コードと照合順序を確認してみます。
#データベース
MariaDB [(none)]>
SELECT SCHEMA_NAME,DEFAULT_CHARACTER_SET_NAME,DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = 'learning_stopwatch';
+--------------------+----------------------------+------------------------+
| SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME |
+--------------------+----------------------------+------------------------+
| learning_stopwatch | latin1 | latin1_swedish_ci |
+--------------------+----------------------------+------------------------+
#テーブル
MariaDB [(none)]>
SELECT TABLE_NAME,TABLE_COLLATION
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='learning_stopwatch';
+---------------------+-------------------+
| TABLE_NAME | TABLE_COLLATION |
+---------------------+-------------------+
| daily_learning_time | latin1_swedish_ci |
| user | latin1_swedish_ci |
+---------------------+-------------------+
データベース、テーブルの文字コードはlatin1
になっていますね。
mariadbの文字コードをもう一度確認すると、
クライアントから受け取る文字コードはutf8mb3
ですが、
データベースの文字コードはlatin1
になっています。
データベースの文字コードをutf8mb3
に変更すれば動きそうです。
MariaDB [(none)]> SHOW VARIABLES LIKE 'chara%';
+--------------------------+------------------------------+
| Variable_name | Value |
+--------------------------+------------------------------+
| character_set_client | utf8mb3 |
| character_set_connection | utf8mb3 |
| 'character_set_database' | 'latin1' |
| character_set_filesystem | binary |
| character_set_results | utf8mb3 |
| character_set_server | latin1 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mariadb/charsets/ |
+--------------------------+------------------------------+
データベースとテーブルの文字コードを変更します。
#まずはデータベースから変更
MariaDB [(none)]>
ALTER DATABASE learning_stopwatch
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
Query OK, 1 row affected (0.035 sec)
MariaDB [(none)]>
SELECT SCHEMA_NAME,DEFAULT_CHARACTER_SET_NAME,DEFAULT_COLLATION_NAME
FROM IMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = 'learning_stopwatch';
+--------------------+----------------------------+------------------------+
| SCHEMA_NAME | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME |
+--------------------+----------------------------+------------------------+
| learning_stopwatch | utf8mb4 | utf8mb4_general_ci |
+--------------------+----------------------------+------------------------+
#つづいてテーブルを変更
MariaDB [learning_stopwatch]>
ALTER TABLE user
CONVERT TO CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
Query OK, 1 row affected (0.217 sec)
Records: 1 Duplicates: 0 Warnings: 0
MariaDB [learning_stopwatch]>
ALTER TABLE daily_learning_time
CONVERT TO CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
Query OK, 0 rows affected (0.029 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [learning_stopwatch]>
SELECT TABLE_NAME,TABLE_COLLATION
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='learning_stopwatch';
+---------------------+--------------------+
| TABLE_NAME | TABLE_COLLATION |
+---------------------+--------------------+
| user | utf8mb4_general_ci |
| daily_learning_time | utf8mb4_general_ci |
+---------------------+--------------------+
これで正常に稼働しました。
セッションタイムアウトの設定
参考:
Spring Boot - セッションタイムアウト時間の設定方法
warビルドの場合
web.xml を作成して設定する。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
TOMCAT_HOME/conf/web.xml でアプリケーションサーバに対するデフォルトのセッションタイムアウト設定することが可能。ただし、ほとんどの場合はアプリケーション個別にセッションタイムアウトを設定したいことのほうが多いと思う。その場合は、アプリケーションプロジェクトに src/main/webapp/WEB-INF/web.xml を作成する。
おわりに
どなたかの参考になれば幸いです。