Raspberry PiでApache2.4＋PHP7.4をソースコンパイルしてWebサーバー構築 - 3.MySQLを使う

# 前提と準備

## Linuxサーバー構築の記事
- [Sambaでファイルサーバー構築(CentOS 8.1・openSUSE 15.1・Ubuntu 20.04)](https://qiita.com/kazumi75kitty/items/4298795029ba9f67b9d2)
- [LinuxでApache2.4＋PHP7.4をソースコンパイル - 1.Apache導入](https://qiita.com/kazumi75kitty/items/daaf8ff8feb50ad04f41) /[【Raspberry Pi】](https://qiita.com/kazumi75kitty/items/67686eccaaec73251458)
- [LinuxでApache2.4＋PHP7.4をソースコンパイル - 2.PHP導入](https://qiita.com/kazumi75kitty/items/fca116b1b387fe56c93c) /[【Raspberry Pi】](https://qiita.com/kazumi75kitty/items/50f1a447f6ebc2ee2b61)
- [LinuxでApache2.4＋PHP7.4をソースコンパイル - 3.MySQL導入](https://qiita.com/kazumi75kitty/items/76807c637c096618a0e1) /【Raspberry Pi：この記事】
- [LinuxでApache2.4＋PHP7.4 - 4.セキュリティ(chownとfirewalld)](https://qiita.com/kazumi75kitty/items/8ad51806ac50bd04b644)
- [LinuxでIPsecゲートウェイをVPN構築 - 1.StrongSwan導入](https://qiita.com/kazumi75kitty/items/60941f00ae91c4d9f555) /[【Ubuntu 20.04＋Raspberry Pi】](https://qiita.com/kazumi75kitty/items/08259681247a6c2ebd0d)
- [LinuxでIPsecゲートウェイをVPN構築 - 2.VPNへの接続確認](https://qiita.com/kazumi75kitty/items/f5a33abda9f8edd5c47f) /[【Ubuntu 20.04＋Raspberry Pi】](https://qiita.com/kazumi75kitty/items/c83f920f052d83d62457)

[前回](https://qiita.com/kazumi75kitty/items/50f1a447f6ebc2ee2b61)はApache2.4にPHP7.4をソースコンパイルでWebアプリ環境を構築しましたが、**残念なことに、標準でRaspberry Pi向けのLinuxは、MySQLをサポートしておらず、RPMやAPTのリポジトリにも存在しません。**ですが、外部MySQLサーバーを接続することは可能です。

簡単なためにWebサーバーと一体でデータベースのMySQLを構築したいと思っても、Raspberry Piの場合はそうにはいかず、たとえインストールできたとしても、microSDの書き込みには非常に不向きなので、今後ラズパイがM.2 SSD相当のストレージに対応しているラインアップを展開すれば、MySQLのサポートも可能かもしれないですが…(✿・ω・)それまではとにかくMySQLを無理にラズパイに導入してストレージにエラーが出ても、またもや本末転倒だしなぁ…

## 環境
- Webサーバープログラム：Apache 2.4.46 ＋ PHP 7.4.10
- クライアント：Windows10 Pro
- サーバーのアーキテクチャ：Raspberry Pi 3B+(armv8搭載) Linuxのディストリビューション：openSUSE 15.1 Leap(64bit) / Raspberry Pi OS 2020.08版(32bit)
- 別途用意する端末：MySQLサーバー(私の場合はCentOS 8.1にMySQL 8.0を構築しました)

## 前提
- ユーザーはrootでインストール(私の検証ではadminという管理者アカウントにて、そこからsudoで処理しています)
- openSUSEではファイアウォールはfirewalldを使う(ディストリビューション独自のファイアウォールコマンドは使用しない)。ラズパイのRaspberry Pi OSでは、firewalldについて、IPv6周りの連動が糞だったので、Debian系標準のufwを使用することにしました。
- [前回](https://qiita.com/kazumi75kitty/items/50f1a447f6ebc2ee2b61)の記事のApache＋PHP導入を完了していること

## サーバー条件
### IPアドレス
- クライアント：192.168.1.11
- Webサーバー：192.168.1.22 (前回まで192.168.1.18でしたが、DBで使われていたので、ラズパイのIPアドレスを変更しました)
- データベースサーバー：192.168.1.18 (ラズパイで使ってたのと重複していたので、ラズパイの方を192.168.1.22に変更しました)
- 所属ネットワークセグメント：192.168.1.0/24
![Webサーバー＋MySQL](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/19dd79f9-ba5a-abd5-c39d-7854a74de369.png "Webサーバーとクライアントのネットワーク図")


### パッケージを個別ダウンロードしてインストールする機能とバージョン(2020年6月時点)
- zlib-1.2.11.tar.gz
- apr-1.7.0.tar.gz
- apr-util-1.6.1.tar.gz
- httpd-2.4.46.tar.gz
- php-7.4.10.tar.gz

それ以外の必要なパッケージは、ディストリビューションの標準パッケージコマンド(dnfやaptなど)でインストールし、個別ダウンロードは不要です。

ダウンロードについては、公式サイトにアクセスして、そこからダウンロードしてFTPで転送するか、ダウンロードファイルのURLさえわかれば、wgetで入手することもできますが、入手方法は省略しています。

# 作業手順
## MySQLクライアントの導入
### MariaDBクライアントツールのインストール
MySQLコマンドを管理するクライアントに、「MySQL」と明確なパッケージは、ラズパイ向けLinuxには含まれていないため、MariaDBクライアントをインストールしました。

```openSUSE15.1(RaspberryPi)
# zypper -n install mariadb-client
```

```RaspberryPiOS(2020.08)
# apt-get -y install mariadb-client
```

これで、MySQLコマンドがラズパイから使えるようになりました。

## MySQLサーバーでの準備
### サーバーでのユーザーとデータベース
今回は、CentOS 8.1にMySQLサーバーを構築した仮想マシンを使うので、[この記事で構築したデータベースを使ってみます](https://qiita.com/kazumi75kitty/items/76807c637c096618a0e1#mysql%E3%82%92%E8%A9%A6%E3%81%99)。

- データベース名：manutest
- テストユーザー名：test
- テストユーザーパスワード：test1
- 文字コード：UTF-8
- MySQLサーバーのIPアドレス：192.168.1.18

なおパスワードは私的都合で「test0」から「test1」に変えました。

### MySQLサーバー上での準備

最初にMySQLが他の端末からアクセスできるように、MySQLサーバーでいろいろ準備します。

MySQLのrootでログインします。

```MySQLサーバー(CentOS8.1)
[このコマンドに限り、MySQLサーバー上で実施するものです]
# mysql -u root -p
Enter password: 　←　MySQLのrootパスワードを入力

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| manutest           |　　←　作成したデータベースが表示される
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> CREATE USER 'test'@'192.168.1.22' IDENTIFIED BY 'test1';
↑ ラズパイのIPアドレス「192.168.1.22」向けのユーザー名「test」を作成する

mysql> GRANT ALL ON manutest.* TO 'test'@'192.168.1.22';
↑ データベース「manutest」に対して「test」が「192.168.1.22」から全機能を使える
```

エラーがなく「Query OK, 0 rows affected」が表示されれば、データベースとユーザーは作成完了。

つまり、MySQLとApacheが同一のサーバーマシンにある場合は「localhost」で済んだが、今回はラズパイ→MySQLサーバーからという、他のサーバーにアクセスするので、以下のように、ユーザー名＋@マーク＋ホスト、というように、

> CREATE USER '<ユーザー名>'@'<ラズパイのホスト>' IDENTIFIED BY '<パスワード>';
> GRANT ALL ON <データベース名>.* TO '<ユーザー名>'@'<ラズパイのホスト>';

というような指定が必要だということですね(˶ ･ᴗ･ )੭

MySQLサーバーでは、CentOSでfirewalldの開放も必要でしたね(˶ ･ᴗ･ )੭\*\*

```MySQLサーバー(CentOS8.1)
[このコマンドに限り、MySQLサーバー上で実施するものです]
# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="3306" protocol="tcp" accept'
# firewall-cmd --reload
```

**MySQLのポートは3306/TCP**なので、そのポートを開放することで、MySQLサーバーにPHPなんかがアクセスできるということ…

### Raspberry Pi→MySQLサーバーに接続できるか確認
MySQLサーバーでの作業はここまで。
では、Raspberry Piに戻って、MySQLを使えるか試します。mysqlコマンドで「-h」オプションでホストを指定できます

```RaspberryPi(ラズパイOS・openSUSE15.1)
# mysql -h 192.168.1.18 -u test -p
Enter password:　　←　パスワード「test1」を入れる
(中略)

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| manutest           |　　←　作成したデータベースが表示されれば成功
+--------------------+
2 rows in set (0.00 sec)
```

![ラズパイ→DBサーバー接続成功！！](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/f900bc59-9c2a-fe7a-c37d-43c896602df3.png)

ちゃんとテーブルの中身も参照できるまでに至りました！！( ˶˙ᵕ˙˶ )

## PHPからMySQLサーバーを使う
### PHPからMySQLの接続を確認
MySQLサーバーには、前回仮想マシンのCentOSで構築したように、テスト用テーブルを使ってみます。

テーブル名：**testtb**

||id|name|memo|
|:-:|:-:|:-:|:-:|
|型|INT|VARCHAR(64)|VARCHAR(256)|
|必須属性|PRIMARY KEY|NOT NULL|初期値NULL|
|その他属性|AUTO_INCREMENT|-|-|

まずはテーブルを使う前に、PHPでMySQLに接続できるかちゃんと確かめないといけません(\*˘ᗜ˘\*;)

接続確認ページを作ります

```
# cd ~
# vi connect.php
```

```php:connect.php
<?php
    $dsn = 'mysql:dbname=manutest; host=192.168.1.18';
    $usr = 'test';
    $pass = 'test1';
    
    try {
        $db = new PDO($dsn, $usr, $pass);
        print 'Connection successful.';
        $db = NULL;
    }
    catch(PDOException $e){
        die('Connect error : '.$e->getMessage());
    }
?>
```

これを、[Apache導入時](https://qiita.com/kazumi75kitty/items/67686eccaaec73251458)にインストールした先のWebページの格納場所 /usr/local/apache2/htdocs/に移動します。

```
# mv connect.php /usr/local/apache2/htdocs/
```

PHPページの配置なので、特にApacheを再起動することは不要なので、https://[LinuxサーバーのIPアドレス]/connect.php と入力して確認。192.168.1.18はMySQLサーバーで使われていて、ラズパイLinuxサーバーのIPアドレスは192.168.1.22なので、ブラウザでhttps:～の後に、192.168.1.22/connect.phpをURLを入力してアクセス。

![ラズパイ上のPHP→DBサーバー接続](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/a6cf585d-50f2-0e93-67ea-dbbf2003f1b1.png)
やっと成功した！！⑅︎◡̈︎*

### PHPからMySQLにデータを登録できるかを確認
続いて、いよいよデータが登録できるかを確認します。
再びWebページを作ります。

まずは登録フォームから。

```
# vi test_form.html
```

```html:test_form.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>テストページ - Test page</title>
</head>
<body>
<form method="POST" action="test_form.php">
    <input type="text" name="name" />
    <input type="text" name="memo" />
    <input type="submit" value="Submit" />
</form>
</body>
</html>
```

続いて、フォームから受け取ったデータをMySQLデータベースへ追加するPHPを作成

```
# vi test_form.php
```

```php:test_form.php
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>テスト入力 - Test insert</title>
</head>
<body>
<?php
    function getDb(){
        $dsn = 'mysql:dbname=manutest; host=192.168.1.18';
        $usr = 'test';
        $pass = 'test1';
        
        try {
            $db = new PDO($dsn, $usr, $pass);
            $db->exec('SET NAMES utf8');
        }
        catch(PDOException $e){
            die('Connect error : '.$e->getMessage());
        }
        
        return $db;
    }
    
    try {
        $db = getDb();
        
        $stt = $db->prepare('INSERT INTO testtb (name, memo) VALUES (:one, :two)');
        
        $stt->bindValue(':one', $_POST['name']);
        $stt->bindValue(':two', $_POST['memo']);
        $stt->execute();
        
        print $_POST['name'].' - '.$_POST['memo'].' : Insert OK.';
        
        $stt = $db->query("SELECT * FROM testtb");
?>
    <table border="1">
<?php
        while($row = $stt->fetch(PDO::FETCH_ASSOC)){
?>
        <tr>
            <td><?php print $row['name']; ?></td>
            <td><?php print $row['memo']; ?></td>
        </tr>
<?php
        }
?>
   </table>
<?php
         $db = NULL;
   }
    catch(PDOException $e){
        die('Process error : '.$e->getMesssage());
    }
?>
</body>
</html>
```

上記2ファイルをApacheのWebページデータの場所へ。

```
# mv test_form.* /usr/local/apache2/htdocs/
```

では、ブラウザでhttps://[IPアドレス]/test_form.htmlにアクセスして、データを登録してみると…

![ラズパイPHP→DBサーバー操作](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617906/d69161dd-2bd9-db82-8526-43467c3b4a40.png)

これも登録成功しました！(˶ ･ᴗ･ )੭⚐⚑
PCより非力かつストレージもmicroSDというDBの読み書きに不向きなラズパイだからこそ、外部のDB用のサーバーと一緒に外部アクセスすることで、ラズパイもDBを扱えることが実感できた瞬間です

# あとがき
Raspberry PiはPCと比べて非力でストレージもmicroSDなので、PCと全く同じようなサーバー構築だと、メモリ不足やデータベースの非対応やらで比較的道のりは険しい一方で、省電力という恩恵ならではのメリットもまたあるということを、今回の構築を通して感銘したな…とも思う(♥´꒳`\*)

# 今後と次回
PHPによるWebアプリサーバー構築のほかにも、Java(OpenJDK)によるWebアプリサーバーについても、構築に触れてみたい