前提と準備
Linuxサーバー構築の記事
- Sambaでファイルサーバー構築(CentOS 8.1・openSUSE 15.1・Ubuntu 20.04)
- LinuxでApache2.4+PHP7.4をソースコンパイル - 1.Apache導入 /【Raspberry Pi】
- LinuxでApache2.4+PHP7.4をソースコンパイル - 2.PHP導入 /【Raspberry Pi】
- LinuxでApache2.4+PHP7.4をソースコンパイル - 3.MySQL導入【この記事】/【Raspberry Pi】
- LinuxでApache2.4+PHP7.4 - 4.セキュリティ(chownとfirewalld)
- LinuxでIPsecゲートウェイをVPN構築 - 1.StrongSwan導入 /【Ubuntu 20.04+Raspberry Pi】
- LinuxでIPsecゲートウェイをVPN構築 - 2.VPNへの接続確認 /【Ubuntu 20.04+Raspberry Pi】
前回はApache2.4にPHP7.4をソースコンパイルでWebアプリ環境を構築しましたが、今回は、前回に引き続き、データベースサーバーを構築します(⑅•ᴗ•⑅)
データベースサーバーはWebサーバー本体と切り離し可能ですが、今回は簡単なため、Webサーバーと一体でデータベースのMySQLを構築します
環境
- Webサーバープログラム:Apache 2.4.43 + PHP 7.4.6 + MySQL 8.0
- クライアント:Windows10 Pro
- サーバーのアーキテクチャ:x64(動作はHyper-Vの第2世代で確認) Linuxのディストリビューション:CentOS 8.1 / openSUSE 15.1 Leap / Ubuntu 20.04(すべて64bit)
前提
- ユーザーはrootでインストール(私の検証ではadminという管理者アカウントにて、そこからsudoで処理しています)
- どのディストリビューションでも、ファイアウォールはfirewalldを使う(ディストリビューション独自のファイアウォールコマンドは使用しない)
- 前回の記事のApache+PHP導入を完了していること
サーバー条件
IPアドレス
- クライアント:192.168.1.11
- Webサーバー:192.168.1.18(どのディストリビューションでも同じIPアドレスで検証)
- データベースサーバー:(Webサーバーと一体)
- 所属ネットワークセグメント:192.168.1.0/24
パッケージを個別ダウンロードしてインストールする機能とバージョン(2020年6月時点)
- zlib-1.2.11.tar.gz
- apr-1.7.0.tar.gz
- apr-util-1.6.1.tar.gz
- mysql80-community-release-el8-1.noarch.rpm (CentOS 8.1)
- mysql80-community-release-sl15-3.noarch.rpm (openSUSE 15.1)
- mysql-apt-config_0.8.15-1_all.deb (Ubuntu 20.04)
- oniguruma-devel-6.8.2-1.el8.x86_64.rpm (CentOS 8.1)
- httpd-2.4.43.tar.gz
- php-7.4.6.tar.gz
それ以外の必要なパッケージは、ディストリビューションの標準パッケージコマンド(dnfやaptなど)でインストールし、個別ダウンロードは不要です。
ダウンロードについては、公式サイトにアクセスして、そこからダウンロードしてFTPで転送するか、ダウンロードファイルのURLさえわかれば、wgetで入手することもできますが、入手方法は省略しています。
作業手順
MySQL 8.0の導入
MySQLのインストール
ディストリビューションの標準パッケージコマンドにあるMySQLは、バージョンが古いものや互換であるMariaDBであることが多いため、明示的なMySQLのバージョンを導入する場合は、MySQL公式からレポジトリをダウンロードする必要があります。
ダウンロードしたレポジトリを適用し、MySQLをインストールします。
# cd [mysql80-community-release-el8-1.noarch.rpmの配置されているディレクトリ]
# dnf -y install mysql80-community-release-el8-1.noarch.rpm
# dnf -y install mysql-server
# cd [mysql80-community-release-sl15-3.noarch.rpmの配置されているディレクトリ]
# zypper install mysql80-community-release-sl15-3.noarch.rpm
…(中略)…
mysql80-community-release-sl15-3.noarch (RPM ファイルキャッシュ): 署名の検証に失敗しました [4-署名の公開鍵がありません]
中止(A)、再試行(R)、無視(I)? [a/r/i] (a): ← 「i」で続行する
# zypper install mysql-community-server
鍵を拒否しますか(R)? 今後ずっと信頼しますか(A)? [r/a/?] (r): ← 「a」で続行する
(あとはインストールするか問われるので「y」を選択)
# cd [mysql-apt-config_0.8.15-1_all.deb.debの配置されているディレクトリ]
# dpkg -i mysql-apt-config_0.8.15-1_all.deb
Which MySQL product do you wish to configure?
→「MySQL Server & Cluster」を選択
Which server version do you wish to receive?
→「mysql-8.0」を選択
Which MySQL product do you wish to configure? に戻る
→「Ok」を選択
# apt-get -y update ← アップデート後は再起動することが望ましい
# apt-get -y install mysql-client mysql-server
→ 途中MySQLのroot(Linuxのrootではない)のパスワードを設定する必要がある
なお、MySQL 8.0の場合認証基盤がハッシュ値対応で、しかもデフォルトでハッシュ値ベースの認証基盤を有効化している場合があります。しかし、これはPHP7でも対応していないらしく(7.4になった今でも対応している話は聞いていない)、PHPで平文パスワードで記載してアクセスすると認証がうまくできない。そのため、/etc/my.cnfを修正する必要がある(CentOS8.1の場合は/etc/my.cnfでインクルードしている/etc/my.cnf.d/mysql-default-authentication-plugin.cnfを編集する)。
またUbuntu 20.04では、MySQLのapt-getでのインストール中に、MySQLのroot(Linuxのrootではない)パスワードの設定と**「Select default authentication plugin」**というように認証基盤の選択ができるのでありがたい(✿´ ꒳ ` )
# vi /etc/my.cnf
# vi /etc/my.cnf.d/mysql-default-authentication-plugin.cnf
default-authentication-plugin = mysql_native_password ← 先頭の「#」ははずす
[認証基盤を/etc/my.cnfの修正で行う必要はない。インストール時に選択する]
インストール中に「Select default authentication plugin」と問われる
→「Use Legacy Authentication Method」を選択する
MySQLの起動
# systemctl start mysqld
# systemctl enable mysqld
# systemctl status mysqld
# systemctl start mysql
# systemctl enable mysql
# systemctl status mysql
次に、MySQLの起動を行った後に、MySQLの初期パスワードを確認するため、MySQLのログを確認。なおUbuntu 20.04ではパスワード設定をあらかじめインストール時に実施したので、初期パスワードをログから確認する作業は不要。
# less -r /var/log/mysql/mysqld.log
# less -r /var/log/mysql/mysqld.log
その際、「[Note] A temporary password is generated for root@localhost:~」が存在すれば、初期パスワードが設定されている。なければ設定されていない(CentOS 8.1のMySQL 8.0は設定されていない)。このパスワードを用いて、MySQLコマンドラインを実行する
[MySQL初期パスワードなし]
# mysql -u root
[MySQL初期パスワードあり]
# mysql -u root -p ← 初期パスワードを入力してログイン
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '<MySQLのrootパスワード(Linuxのrootパスワードではない)>';
Query OK, 0 rows affected (0.00 sec)
mysql> exit
ここで、MySQLの実際に運用想定のパスワードを設定する。そこで、rootというのはLinuxのrootではなく、MySQLの中のrootであることに注意したい。
「Query OK, 0 rows affected (0.00 sec)」と出力されれば、MySQLのrootパスワードの設定が完了するので、exitで終了する。
では、設定後のMySQLのrootパスワードでログインを試す
# mysql -u root -p
Enter password: ← MySQLのrootパスワードを入力
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 8.0.17 Source distribution
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
こうなればMySQLのrootログインが成功となる。または、以下でも確認できた
# mysqladmin ping -u root -p
Enter Password: ← MySQLのrootパスワードを入力
mysqld is alive
「mysqld is alive」となればOK
MySQLを試す
ユーザーとデータベースを作ってみる
MySQLが動いたということなので、実際ユーザーとデータベースを作ってみます。
- データベース名:manutest
- テストユーザー名:test
- テストユーザーパスワード:test0
- 文字コード:UTF-8
最初にMySQLのrootでログインします。
# mysql -u root -p
Enter password: ← MySQLのrootパスワードを入力
mysql> CREATE DATABASE manutest CHARACTER SET utf8;
↑ データベース「manutest」を文字コードUTF-8で作成する
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| manutest | ← 作成したデータベースが表示される
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> CREATE USER 'test'@'localhost' IDENTIFIED BY 'test0';
↑ ユーザー名「test」をパスワード「test0」にて作成する
mysql> GRANT ALL ON manutest.* TO 'test'@'localhost';
↑ データベース「manutest」に対して、ユーザー「test」が全機能を使えるようにする
エラーがなく「Query OK, 0 rows affected」が表示されれば、データベースとユーザーは作成完了。
パスワードポリシーエラーが発生する場合
もしパスワードポリシーに反しているとエラーが発生してしまう場合は、ポリシーの状態を確認して、変更できるみたいです。ちなみにCentOS 8.1では存在せず、openSUSE 15.1では存在していました。
mysql> SHOW VARIABLES LIKE 'validate_password%';
↑ Empty setならポリシーは存在しないが、もし存在する場合は、初期では
validate_password_lengthが8、validate_password.policyが「MEDIUM」
mysql> SET GLOBAL validate_password.length=4;
mysql> SET GLOBAL validate_password.policy=LOW;
↑ これで4文字以内のパスワード、試験目的で簡単なパスワードを設定できる
mysql> SET GLOBAL validate_password.length=8;
mysql> SET GLOBAL validate_password.policy=MEDIUM;
↑ 戻す場合
では、作成したテスト用のユーザーとデータベースで、MySQLを使えるか試します。
mysql> exit
Bye
# mysql -u test -p
Enter password: ← パスワード「test0」を入れる
(中略)
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| manutest | ← 作成したデータベースが表示されれば成功
+--------------------+
2 rows in set (0.00 sec)
テーブルを作成してデータを入れてみる
では、作成したデータベースに、テーブルを作ってそこにデータを入れてみます!
今回は、このテーブルをテスト用に作成します。
テーブル名:testtb
id | name | memo | |
---|---|---|---|
型 | INT | VARCHAR(64) | VARCHAR(256) |
必須属性 | PRIMARY KEY | NOT NULL | 初期値NULL |
その他属性 | AUTO_INCREMENT | - | - |
mysql> USE manutest;
mysql> CREATE TABLE testtb (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(64) NOT NULL, memo VARCHAR(256) DEFAULT NULL);
Query OK, 0 rows affected (0.11 sec)
mysql> SHOW TABLES;
+--------------------+
| Tables_in_manutest |
+--------------------+
| testtb |
+--------------------+
1 row in set (0.00 sec)
テーブルの作成に成功したら、実際にデータを入れてみます。
テストテーブルtesttbは、idが自動採番で、nameが必須入力となるため、例として以下の値を挿入します。
- id:(自動採番のため省略)
- name:テスト
- memo:Only for test.
mysql> INSERT INTO testtb (name, memo) VALUES ('テスト', 'Only for test.');
mysql> SELECT * FROM testtb;
+----+-----------+----------------+
| id | name | memo |
+----+-----------+----------------+
| 1 | テスト | Only for test. |
+----+-----------+----------------+
1 row in set (0.00 sec)
このように登録したデータが文字化けすることなくデータベースに登録されました♪
成功です!
PHP上でMySQLを扱ってみる
MySQLのインストールも、動作も問題なく確認できたので、いよいよPHPからMySQLを扱ってみたいと思います。
MySQLは終了して、PHPページを作成します。
PHPからMySQLの接続を確認
まずはPHPでPOSTにて受け取ったデータをMySQLデータベースへ登録する受信PHPを作成します!っとその前に、PHPでMySQLに接続できるかちゃんと確かめないといけません(*˘ᗜ˘*;)
接続確認ページを作ります
# cd ~
# vi connect.php
<?php
$dsn = 'mysql:dbname=manutest; host=127.0.0.1';
$usr = 'test';
$pass = 'test0';
try {
$db = new PDO($dsn, $usr, $pass);
print 'Connection successful.';
$db = NULL;
}
catch(PDOException $e){
die('Connect error : '.$e->getMessage());
}
?>
これを、Apache導入時にインストールした先のWebページの格納場所 /usr/local/apache2/htdocs/に移動しましょう!
# mv connect.php /usr/local/apache2/htdocs/
PHPページの配置なので、特にApacheを再起動することは不要なので、https://[LinuxサーバーのIPアドレス]/connect.php と入力して確認。今回はLinuxサーバーのIPアドレスは192.168.1.18なので、ブラウザでhttps:~の後に、192.168.1.18/connect.phpをURLを入力してアクセス。
connect.phpでは接続成功すると上記のメッセージを出力するので、↑の画像は接続が成功したんです!!
PHPからMySQLにデータを登録できるかを確認
続いて、いよいよデータが登録できるかを確認します。
再びWebページを作ります。
まずは登録フォームから。
# vi 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
<!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=127.0.0.1';
$usr = 'test';
$pass = 'test0';
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にアクセスしてみます。
適当に左右のフォームに文字列を入れて…(なるべく日本語で)、Submitを押します
成功しました!入力されたデータがPHPにPOSTされて、MySQLのデータベースに登録されました。ではコマンドラインからも確認してみましょう。
PHPでは、manutestというデータベースに、ユーザーtestで接続しているので、コマンドからもtestでMySQLにログインします。
# mysql -u test -p
Enter password: ← パスワード「test0」を入力
mysql> USE manutest;
mysql> SELECT * FROM testtb;
+----+-----------------+----------------+
| id | name | memo |
+----+-----------------+----------------+
| 1 | テスト | Only for test. |
| 2 | パンケーキ | 食べたい |
+----+-----------------+----------------+
2 rows in set (0.00 sec)
ちゃんと追加されていました!!(*˘ᗜ˘*).。.:*♡
あとがき
ApacheとPHP+MySQLは、私の過去の実務経験からも、大企業までも頻繁にこのパターンで使われていました。逆にJavaは少なかったかな…と感じています。
PHPのほうがJavaの商用ライセンスよりも安価でオープンなので、大企業でも、もちろん中小個人でも導入しやすいのかな…って感じがします。
LinuxへのApache+PHP+MySQLに導入する費用としては、ライセンスがいらないので、あとは給料に対する労力の費用と、中古PCやラズパイ関係なく、装置の費用なのかな…と感じがします。
導入費用が1時間2500円であれば、Webサーバーとファイルサーバーを新規構築するのに2時間かければ、合計5000円。それに、中古PC or ラズパイとHDDやSSDの新品の組み合わせが3~40000円となれば、新規導入費用は5万円弱なので、高価なWindows Serverマシンを30万円かけて買うよりは、6分の1以下と、中小企業や個人経営程度でもITソリューションの潤いはやってくるのかな…と感じる。
特に、ラズパイなどIoTの場合は、センサーなどの物性分野とハイブリッドで組み合わせて、データ化できるのも期待されるので、今後はいろいろと視野を広げて、Qiitaに載せてみたいと思う( ˙꒳˙ᐢ )
今後と次回
PHPによるWebアプリサーバー構築のほかにも、Java(OpenJDK)によるWebアプリサーバーについても、構築に触れてみたい