Dockerを超初心者が試してみる(4)PHP+Apacheコンテナから、MySQLコンテナに接続

PHPとApachが合体したコンテナから、MySQLのコンテナに接続してみたいと思います。

2つのコンテナを利用する例を調べるとdocker-compose.ymlを使う説明がほとんどです。

私はDockerを使い始めたばかりで

  1. イメージとかコンテナとか混乱してるし
  2. docker runとか使ったばかりなのに
  3. いきなりdocker-compose.ymlなんて分からない

という状態です。

なので、docker-compose.ymlを使わずに、シンプルに手動で2つのコンテナを起動して試してみることにしました。

作ってみたのは2つのコンテナです。

元になるイメージは、php+apacheもmysqlも最新のバージョンを使う使うことにします。

作成する2つのコンテナ

(1)PHP+Apacheのコンテナ

  • ブラウザでPHPを実行し、別のMySQLコンテナに接続してデータを取得します。
  • コンテナ名:phpapache001
  • 利用するイメージ:php:apache

(2)MySQLのコンテナ

PHP+Apacheのコンテナから接続され、データベース内のデータを提供します。

  • コンテナ名:mysql001
  • 利用するイメージ:mysql

どちらのイメージもバージョンを指定しないので最新のバージョンが利用されます。

MySQLのコンテナを作成する

先にMySQLのコンテナから作ります。

MySQLのコンテナが起動していないと、それを利用するPHP+Apacheのコンテナが起動できないためです。

 

  1. コンテナmysql001を作り
  2. コンテナの中に入って、サンプルデータを作成
  3. PHPのPDOを利用して接続できるようにmy.cnfを読み込めるようにする

コンテナmysql001を作成する

次のように指定しました。

$ docker run --name mysql001 -v $PWD:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=mypass -d mysql

–name:コンテナの名前(mysql001)

-v:設定ファイル(my.cnf)をおくディレクトリの指定

-e:環境変数(ここではルートのパスワードを指定)

-d:コンテナをバックグラウンドで動かす

最後のmysqは利用するイメージ名です(自動的にダウンロードされる)

 

my.cnfは、PHPのPDOを使ってMySQL(今回のバージョンはlatestの8)に接続するときに必要になります。

MySQLが起動すると/etc/mysql/conf.dにあるファイルを自動的に読み込みます。

-vでローカルとコンテナ側のディレクトリを結びつけておけば、ローカルのmy.cnfを自動的にコンテナのMySQLが読み込んでくれます。

my.cnfの中身

$ cat my.cnf
[mysqld]
default_authentication_plugin=mysql_native_password

MySQL 8をPODで利用するときに必要なので設定しました。

コンテナに入ってサンプルデータを作成

コンテナに入って、接続確認用のサンプルのデータベースを作りました。

$ docker exec -it mysql001 bash
root@516b30ea52ce:# mysql -u root -p
Eneter password:

パスワードはrunで指定した「mypass」を入力しています。

-it:-iオプションと-tオプションを同時に指定。「-t -i」「-ti」としても同じ。

ターミナル画面からコンテナ内部に接続して操作するために必要なオプションです。

 

次のようにしてサンプルを作りました(適当です)。

mysql> create database sample;
mysql> use sample;
mysql> create table sample (id int, name varchar(20));
mysql> show columns from sample;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+

とりあえずデータを入れておきます。

mysql> insert into sample (id, name) values (1, "test");
mysql> select * from sample;
+------+------+
| id | name |
+------+------+
| 1 | test |
+------+------+

これでMySQL側のコンテナの準備は完了です。

MySQLを終了して、コンテナからも終了します。

mysql> \q
root@516b30ea52ce:# exit

PHP+Apacheのコンテナを作成する

  1. コンテナphpapache001を作り
  2. コンテナの中に入ってPDOのドライバをインストール
  3. コンテナを再起動

の順に行いました。

コンテナphpapache001を作成する

次のように指定しました。

$ docker run --name phpapache001 -v $PWD:/var/www/html -p 8090:80 --link mysql001 -d php:apache

–name:コンテナの名前(phpapache001)

-v:phpファイルを読み込ませるためのディレクトリの指定

Apacheがデフォルトで読み込むディレクトリは/var/www.htmlなので、それをカレントディレクトリに結びつけています。

-p:ローカルの任意のポート8090を、apacheのデフォルトポート80に結びつけています。

–link:利用するMySQLのコンテナ名を指定

-d:バックグラウンドで動かす

php:apacheはコンテナ作成の元になるイメージです(自動的にダウンロードされる)

 

コンテナが起動したら、ブラウザから確認しておきましょう。

次の内容のindex.phpをカレントディレクトリに置いて

$ cat index.php
<?php phpinfo(); ?>

「localhost:8090」

とするとPHP Info画面が表示されました。

 

画面を下のほうままで見ていくと「PDO drivers」の項目があります。

表示されているのは「sqlite」

PDOで接続できるためには、ここにmysqlが表示されている必要があります。

そのためにコンテナの中にドライバをインストールしましょう。

コンテナにドライバをインストールする

コンテナに入ってbashシェルを起動します。

$ docker exec -it phpapache001 bash

-itオプションの意味は、MySQLのときと同じです。

 

今回はPDOを使って接続するのでドライバ「pdo_mysql」を入れました。

まずコンテナの中をアップデートしてからインストールします(らしい)。

root@406ac9d87529:/var/www/html# apt-get update
root@406ac9d87529:/var/www/html# docker-php-ext-install pdo_mysql

「docker-php-ext-install」は、php:apacheイメージから作ったコンテナにドライバをインストールするために必要らしい(あまり理解していない)。

コンテナを再起動してドライバを有効にする

インストールしたPDOドライバを有効にするにはコンテナを再起動する必要があります。

(コンテナphpapache001が提供しているhttpdサーバを再起動するということですが)。

$ docker stop phpapache001
$ docker start phpapache001

再びブラウザから

「localhost:8090」

としてPODの項目を見ると

PDO driversの項目は、sqlite, msql

と今回は表示されました。

ブラウザから接続してみる

2つのコンテナの設定が終ったので、ブラウザからからMySQLのコンテナに接続してみます。

サンプルに使ったのは次のファイルです。

$ cat foo.php
<?php
$dsn = 'mysql:dbname=sample;host=mysql001';
$user = 'root';
$password = 'mypass';
$dbh = new PDO($dsn, $user, $password);

$sql = 'SELECT id,name FROM tbl WHERE 1';
$stmt = $dbh->prepare($sql);
$stmt->execute();

$dbh = null;
while (true) {
  $rec = $stmt->fetch(PDO::FETCH_ASSOC);
  if ($rec == false) {
    break;
  }
  print 'id=' . $rec['id'] . '<br>';
  print 'name=' . $rec['name'] . '<br>';
}
?>

ブラウザからから

localhost:8090/foo.php

を実行して、サンプルに入れたレコード内容が表示されるのを確認しました。

 

今回の目的はここまでです。

終了して、ふたたび起動するには

2つのコンテナ「mysql001」「phpapache001」を終了するには

$ docker stop mysql001 phpapache001

再び起動するには、

$ docker start mysql001 phpapache001

です。ここでもmysql001を先に起動しないと、エラーになります。

まとめ

  • PHP+Apacheのコンテナ
  • MySQLのコンテナ

この2つを連動させるだけで手間がかかりました。

試行錯誤して何度かコンテナを作り直したので、そのたびにドライバのインストールをしなければならないのも手間です。

 

Dockerfileを使うと「わざわざコンテナに入って毎回ドライバをインストール」という手間が省けます。

さらに、docker-compose.ymlを使うと、2つのコンテナを一気に作ることができるらしい。

ということで、次回は、Dockerfileとdocker-composeを使って、この記事と同じことを再現する予定です。

コメント