北海道のcarametal

北海道のプログラマによる技術とか雑記のブログ

Dockerを使ってPHP7+Apache+MySQLの開発環境を作る

今回は前回に引き続き実技試験の予習として開発環境を作っていく

前回はPHP7+Apacheまで作ったのでMySQLを含めた環境を作っていく
carametal.hatenablog.com

こちらの記事を参考にさせていただきました。

qiita.com

こちらの記事ではMySQLクライアントにphpMyAdminを使っていますが
ひとまず環境構築のみの目的なのでphpMyAdminは扱いません。

前回の記事ではDockerfileを用いていましたが今回はdocker-composeで環境を作っていきます。

手始めにdocker-compose.ymlを作成

version: '3'

services:
  php:
    image: php:7.2-apache
    volumes:
      - ./html:/var/www/html
    ports:
      - 8000:80
    container_name: php7.2-trial2
  mysql:
    image: mysql:5.7
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=test
      - MYSQL_USER=test
      - MYSQL_PASSWORD=test
    container_name: mysql5.7-trial2
    

ほとんど参考にさせていただいた記事からの流用ですが

phpのimageは前回記事同様にphp:7.2-apacheを使用
volumes項目でカレントディレクトリにあるhtmlディレクトリを
コンテナ内の/var/www/htmlにマウント
公開ポートは8000番、ポートフォワーディング先は80番に指定
ビルド後のコンテナ名にphp7.2-trial2を指定

mysqlのimageにはmysql5.7を使用
volumes項目で./mysqlを/var/lib/mysqlにマウント(ここはよくわかっていないけどディレクトリがなくてもdocker-compose up したときに自動的に作られるみたい※要調査)
environment項目では環境変数を設定し
コンテナ名にmysql5.7-trial2を指定

docker-compose.ymlはこれで完了

htmlディレクトリにはindex.phpを配置する

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>php7.2-apache</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<?php
    echo 'Hello world.';
?>
</body>
</html>mysql5.7-trial2

index.phpは一旦echoでHello world.するようにする(あとでDBのデータを取得するように変更します)

最後にphp.ini
phpの設定ファイルなわけですが今回はお試し環境構築なのでこちらから拝借させていただきました
qiita.com

以上で必要なファイルはそろいました

docker-compose up -d 

でコンテナの作成&実行する

docker container ps

を実行してphp7.2-trial2とmysql5.7-trial2の2つのコンテナが起動していれば成功

http://localhost:8000/にアクセスしてHello worldと表示されるはず

次はMySQLにアクセスしてDBから取得したtextを表示してみる

まずはmysql5.7-trial2コンテナに入って

docker exec -it mysql5.7-trial2 bash

MySQLにログイン

mysql -uroot -proot
  • uはログインユーザの指定
  • pはパスワードの指定

この2つはdocker-composeで指定したものを使用する

mysqlにログインできたら

show databases;

とするとMYSQL_DATABASEにtestと設定しているので一覧にtestというDBがあるはず

use test;
show tables;

当然まだtableはまだないはずなのでEmpty set (~~~ sec)と表示されるはず

tableを作ってテストデータを作る

create table test (id int not null auto_increment, text char(30), primary key (id));
insert into test (text) values ('first test.');
insert into test (text) values ('second test.');
insert into test (text) values ('second test.');
select * from test;

+----+--------------+
| id | text         |
+----+--------------+
|  1 | first test.  |
|  2 | second test. |
|  3 | third test.  |
+----+--------------+

これが出たら準備は完了

index.phpを修正する

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>php7.2-apache</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<?php
try {
    $dbh = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
    foreach($dbh->query('select * from test') as $row) {
        echo $row['text'] . '<br>';
    }
    $dbh = null;
} catch (PDOException $e) {
    echo $e;
    die();
}
$dbh = null;
?>
</body>
</html>

これでtestデータベースのtestテーブルのデータが表示される

と思ったが

Fatal error: Uncaught PDOException: could not find driver in /var/www/html/index.php:11

というエラーが

どうやらPDO(PHP Data Object)にMySQL用のドライバーがないというエラーの模様

今回の対応として公式のphp:7.2-apacheではなくドライバー入りのimageを作って
そっちを使うようにする

まず、以下のようなDockerfileを作る

FROM php:7.2-apache
RUN docker-php-ext-install pdo_mysql

そしてこれをbuildする

docker image build -t php7.2-apache-trial2 .
||>

このとき、php.iniやhtmlディレクトリのあるディレクトリでビルドすると下記のようなエラーが出ることがあるので注意

>||
error checking context: 'no permission to read from '/home/carametal/dev/docker/soltwarks/trial2/mysql/ca-key.pem''.

これはカレントディレクトリ配下をDockerfile内の命令からアクセス可能な範囲として指定されるため発生するらしい(以下の記事参照)
developer-collaboration.com

imageのビルドができたらdocker-compose.ymlを修正

version: '3'

services:
  php:
    image: php7.2-apache-trial2
    volumes:
      - ./html:/var/www/html
    ports:
      - 8000:80
    container_name: php7.2-trial2

  mysql:
    image: mysql:5.7
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=test
      - MYSQL_USER=test
      - MYSQL_PASSWORD=test
    container_name: mysql5.7-trial2

phpの指定imageをphp:7.2-apacheから今回新しくbuildしたphp7.2-apache-trial2に変更するだけ

さぁこれでDBから取得したデータが表示されるはず

PDOException: could not find driver in /var/www/html/index.php:12 Stack trace: #0 /var/www/html/index.php(12): PDO->__construct('mysql:host=mysq...', 'root', 'root') #1 {main}

と思いきやこのようなエラーメッセージが出てきてしまった

これは正直めちゃくちゃハマったんだけどこちらの記事のおかげで助かりました
qiita.com
内部的にどんな処理になってるのかわからないんだけど
PDOのコンストラクタに渡すhostはlocalhostではだめで

<?php
// NG
$dbh = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
//OK
$dbh = new PDO('mysql:host=mysql5.7-trial2;dbname=test', 'root', 'root');

docker-compose.ymlのcontainer_nameで指定しているコンテナ名にしなければならないらしい
ローカルにそのままMySQLサーバーを立てるんだったらlocalhostでいいんだろうけど
Dockerを使っている場合はコンテナ名を指定しなきゃいけない

ということでhttp://localhost:8000/にアクセスしたら

first test.
second test.
third test.

と表示されます

なんとかphp7+Apache+MySQL開発環境をDockerで作る目標を達成しました。

Dockerもいいけど明日からは実技試験に向けてPHPのコードを書いていきたい

面接とSPI試験の対策もしておかなきゃなぁ