Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

LinuxでApache2.4(httpd 2.4.43)+PHP7.4をソースコンパイルしてWebサーバー構築 - 3.MySQL8.0導入編

前提と準備

Linuxサーバー構築の記事

前回は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 Webサーバー.png

パッケージを個別ダウンロードしてインストールする機能とバージョン(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をインストールします。

CentOS8.1
# cd [mysql80-community-release-el8-1.noarch.rpmの配置されているディレクトリ]
# dnf -y install mysql80-community-release-el8-1.noarch.rpm
# dnf -y install mysql-server
openSUSE15.1
# 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」を選択)
Ubuntu20.04
# 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」というように認証基盤の選択ができるのでありがたい(✿´ ꒳ ` )

openSUSE15.1
# vi /etc/my.cnf
CentOS8.1
# vi /etc/my.cnf.d/mysql-default-authentication-plugin.cnf
my.cnfまたはmysql-default-authentication-plugin.cnf
default-authentication-plugin = mysql_native_password ← 先頭の「#」ははずす
Ubuntu20.04の場合
[認証基盤を/etc/my.cnfの修正で行う必要はない。インストール時に選択する]
インストール中に「Select default authentication plugin」と問われる
→「Use Legacy Authentication Method」を選択する

MySQLの起動

CentOS8.1
# systemctl start mysqld
# systemctl enable mysqld
# systemctl status mysqld
openSUSE15.1・Ubuntu20.04
# systemctl start mysql
# systemctl enable mysql
# systemctl status mysql

次に、MySQLの起動を行った後に、MySQLの初期パスワードを確認するため、MySQLのログを確認。なおUbuntu 20.04ではパスワード設定をあらかじめインストール時に実施したので、初期パスワードをログから確認する作業は不要。

CentOS8.1
# less -r /var/log/mysql/mysqld.log
openSUSE15.1
# less -r /var/log/mysql/mysqld.log

その際、「[Note] A temporary password is generated for root@localhost:~」が存在すれば、初期パスワードが設定されている。なければ設定されていない(CentOS 8.1のMySQL 8.0は設定されていない)。このパスワードを用いて、MySQLコマンドラインを実行する

Ubuntu20.04はこの手順は飛ばす
[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
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を入力してアクセス。

conn.png
connect.phpでは接続成功すると上記のメッセージを出力するので、↑の画像は接続が成功したんです!!

PHPからMySQLにデータを登録できるかを確認

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

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

# vi test_form.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
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にアクセスしてみます。

reg1.png
適当に左右のフォームに文字列を入れて…(なるべく日本語で)、Submitを押します

reg2.png
成功しました!入力されたデータが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アプリサーバーについても、構築に触れてみたい

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
2
Help us understand the problem. What are the problem?