DockerでPHP+MySql環境構築

WebサイトをPHPで開発する場合、データベースを利用することが多いでしょう。そして公開する場合Linuxを選択することも多いです。

Dockerを使えばそのような環境を簡単に手に入れることができ、確認や開発の効率アップが期待できます。

今回は、Windows10(以下ホスト)上にDockerを使ってLinux環境を構築し、PHPとMySqlの環境を整えます。

スポンサーリンク

前提環境

  • Windows10
  • Docker Compose

Docker Compose はサイトでインストーラが配布されていると思うので、簡単に準備できるでしょう。

バージョン確認

> docker -v
Docker version 20.10.5, build 55c4c88

> docker-compose -v
docker-compose version 1.29.0, build 07737305

フォルダ構成

c:\project\php-test\  ・・・プロジェクトフォルダ
 ├ docker\
 │  ├ mysql\
 │  │  ├ conf\
 │  │  ├ data\
 │  │  └ sql\
 │  │     └ 000.sql
 │  └ php\
 │     ├ Dockerfile
 │     └ php.ini
 ├ src_php\
 │  └ index.php
 └ docker-compose.yml

プロジェクトフォルダは好きな場所に好きな名前で作成して問題ありません。

ファイルはテキストエディタ等で作成します。vsCodeを使用する場合は、プロジェクトフォルダの上で右クリックし、「Codeで開く」を選択すると起動できます。

docker-compose.yml 作成

Docker Compose を使えばいろいろなサービスをまとめて管理・起動できて便利です。

version: "3"
services:
  php:
    build:
      context: ./docker/php
    ports:
      - 8080:80
    volumes:
      - ./src_php:/var/www/html
      - ./docker/php/php.ini:/usr/local/etc/php/php.ini

  mysql:
    image: mysql:5.7
    restart: always
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci --default-time-zone=Asia/Tokyo
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=test_db
      - MYSQL_USER=docker
      - MYSQL_PASSWORD=docker
    volumes:
      - ./docker/mysql/data:/var/lib/mysql
      - ./docker/mysql/conf:/etc/mysql/conf.d/
      - ./docker/mysql/sql:/docker-entrypoint-initdb.d
    ports:
      - 13306:3306

  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=mysql
      - PMA_USER=root
      - PMA_PASSWORD=root
    ports:
      - 8082:80
    volumes:
      - ./docker/phpmyadmin/sessions:/sessions      

Web サービス

WebサービスはPHPで構築(名前は「php」)します。

build で指定した「docker/php」フォルダに、Dockerfileを作成することで、その内容でサービスが起動します。

コンテナ内では、標準でポートが80のWebサイトが起動するので、ホストからは8080で接続できるよう指定しています。ホストからは「http://localhost:8080」にアクセスすると表示されます。ホストで8080のポートを既に使用している場合は、他の空いている番号を指定する必要があります。

また、コンテナ内の「/var/www/html」がWebサイトの公開フォルダになるので、ホストの「src_php」フォルダと紐づけ、そこにPHPファイルを置くことでブラウザで表示されることになります。

同様にPHPの設定ファイルも「./docker/php/php.ini」に置けば「/usr/local/etc/php/php.ini」紐づき、反映されます。

DB サービス

DBサービスはMySqlで構築(名前は「mysql」)します。

command で character-set や timezone を指定すると良いようです。

environment で root のパスワードや初期DB、接続ユーザを指定しています。

DBのデータを永続化するため、「/var/lib/mysql」をホストの「./docker/mysql/data」フォルダと紐づけ、ホスト側に保存しているので、Dockerを終了(Down)しても削除されません。

構成ファイル(my.cnf)を使用する場合は、ホストの「./docker/mysql/conf」フォルダに置いておくことで「/etc/mysql/conf.d/」に紐づけられ、反映されます。

DBのダンプファイルなど初回に実行したいSQLなどがあれば、.sh、.sql、.sql.gz ファイルをホストの「./docker/mysql/sql」フォルダに置いておくことで「/docker-entrypoint-initdb.d」に紐づけられ、アルファベット順に実行されます。

ポートはホストから13306で接続できる設定としています。

phpMyAdmin

DBを操作・管理できるphpMyAdminもついでに導入します。

environment で mysql に接続する情報を指定します。

ポートは8082を指定しているので、ホストから「http://localhost:8082」にアクセスすると表示されます。

セッション情報をホストの「./docker/phpmyadmin/sessions」フォルダに紐づけて永続化しています。省略するとごみデータが残るらしいので、念のため指定しています。

000.sql 作成(DB初期データ登録)

DBの初期データとして、テーブルの作成とデータの追加をします。

create table t_test(
    date DATETIME
);

INSERT INTO t_test (date) VALUES (now());

Dockerfile 作成

PHPが動作するWebサービスの環境(Linux)の構築内容を指定します。

MySqlに接続するためのライブラリをインストールします。

FROM php:7.2-apache

RUN apt-get update \
    && docker-php-ext-install mysqli

php.ini 作成

timezoneを指定しています。

[Date]
date.timezone = "Asia/Tokyo"

index.php 作成

MySqlに接続して確認するための処理を記述します。

<?php
$now = date('Y-m-d H:i:s');
echo "現在:" . $now . '</br>';

// host, user, password, db
$mysqli = new mysqli('mysql', 'docker', 'docker', 'test_db');

if ($mysqli->connect_error) {
  echo $mysqli->connect_error;
  exit();
}

echo "アクセス履歴:</br>";
$sql = "SELECT date FROM t_test ORDER BY date DESC";
if ($result = $mysqli->query($sql)) {
    While($row = $result->fetch_assoc())
    {
        echo ' ' . $row['date'] . '</br>';
    }
}

$sql = "INSERT INTO t_test(date) VALUES(now())";
$result = $mysqli->query($sql);

$mysqli->close();

最初に現在時刻を取得し表示しています。php.iniでtimezoneを指定しなかった場合はUTC(日本時間 -9時間)で表示されます。

次に、host名、user、password、db名 を指定してMySqlに接続し、エラーの場合はその内容を表示し、終了(exit())します。

MySqlに接続できたら、その内容を列挙して表示します。

その後、現在の日時をMySqlに登録し、最後にMySqlの接続を閉じます。

起動

Docker Compose 起動

PowerShellを起動し、プロジェクトフォルダに移動します。vsCodeのTerminalを使用しても構いません。

> cd c:\project\php-test

まず、ビルドをしてみます。「Successfully」となればOKです。

> docker-compose build
 ・・・
Successfully built 004d3052・・・

Dockerを起動します。すべて「done」となれば起動完了です。vsCodeに拡張機能の「Docker」を入れておけば、Dockerの状態等を簡単に確認できるので便利です。

> docker-compose up -d
 ・・・
 Creating docker-php-mysql_mysql_1      ... done
Creating docker-php-mysql_php_1        ... done
Creating docker-php-mysql_phpmyadmin_1 ... done

ホストでブラウザを起動し、「http://localhost:8080」にアクセスすると、「index.php」が処理され結果が表示されます。

一番下の日時は000.sqlで now() を使って追加した初期データで、UTC(日本時間 -9時間)になっています。通常は、他のDBのダンプなどから初期データを作ると思うので、now() ではなく決まった日時が指定され問題にならないと思いますが、000.sqlの先頭に以下を追加して timezone を指定すれば日本時間で登録されました。

SET time_zone = 'Asia/Tokyo';

PDOでDB接続

PDOを使えば、他のDBを利用する場合や変更する場合、プログラムをほとんど変更することがないので、PDOを使うのがお薦めです。

FROM php:7.2-apache

RUN apt-get update \
    && docker-php-ext-install pdo_mysql
<?php
$now = date('Y-m-d H:i:s');
echo "現在:" . $now . '</br>';

$dsn = 'mysql:dbname=test_db; host=mysql; charset=utf8';
$user = 'docker';
$pass = 'docker';

try {
    $db = new PDO($dsn, $user, $pass);
  
    echo "アクセス履歴:</br>";
    $sql = "SELECT date FROM t_test ORDER BY date DESC";
    if ($stt = $db->query($sql)){
        While($row = $stt->fetch(PDO::FETCH_ASSOC)) {
            echo ' ' . $row['date'] . '</br>';
        }
    }

    $sql = "INSERT INTO t_test(date) VALUES(now())";
    $stt = $db->query($sql);

} catch (PDOException $e) {
    echo "{$e->getMessage()}";
} finally {
    $db = null;
}

リンク

Docker ドキュメント日本語化プロジェクト

コメント

タイトルとURLをコピーしました