⚔️

Docker Composeを使ってphpからMySQL/MariaDBに接続する環境を作る

2021/11/24に公開

Webシステム開発で必ず出てくるデータベース(DB)。
phpからDBに接続してデータを取得/操作することは日常茶飯事です。
今回はDocker Composeを使ってどう実現するかを説明します。

今はMySQLと互換性があるMariaDBが使われることも多いのでMySQL/MariaDB両方の接続パターンを例示します。
とはいえ、1箇所しか違いはありません。
ついでにphpMyAdminコンテナも導入してみます。
※個人的にはTablePlusのようなDBクライアントを使うのでphpMyAdminコンテナは入れていません。
今回は後述する動作確認説明のため導入します。

※Mac Arm64環境で動作しません。
対応版を別記事にしました。
Docker Composeを使ってphpからMySQLに接続する環境を作る(Apple Silicon arm64)

前提

  • httpのコンテナだけを構築していて、phpのみインストールされている状態です。
  • httpコンテナは「Dockerfile」を使ってビルドしています。
  • htmlファイルはホスト環境にあるものをバインドマウントで永続化しています。
  • 追加するDB用コンテナのデータもバインドマウントで永続化します。

具体的には以下のファイル構成/内容です。
最低限ではありませんが、それに近い内容です。
ここからDB接続もできるようにしていきます。
Macで動作確認していますが、Windows/Linuxでも方法はほぼ同じです。

# ファイル構成

├── docker
│   ├── docker-compose.yml
│   └── web
│       └── Dockerfile
└── html

手順(MySQLコンテナを追加して連携)

データディレクトリを用意

データの永続化です。
コンテナを削除してもデータが消えないようにデータディレクトリを用意します。
ディレクトリの名前は何でもよいです。
ここでは「mysql_data」としました。
後でDockerfileに追記します。

# ファイル構成

├── docker
│   ├── docker-compose.yml
│   └── db
│       └── mysql_data
│   └── web
│       └── Dockerfile
└── html

MySQLの設定ファイルを作成

MySQLの設定ファイルとなるmy.cnfをホスト環境で作成します。

# db/my.cnf
[mysqld]
character-set-server=utf8
datadir = /var/lib/mysql
socket = /tmp/mysql.sock

Dockerfileを作成

DB用のコンテナを起動させるためのDockerfileを作成します。
MariaDBを動かす場合は下記イメージ指定を変更するだけでOKです。

FROM mysql:5.7
# MariaDBを動かす場合の記述
# FROM mariadb:10.6

RUN apt-get update

COPY ./my.cnf /etc/mysql/my.cnf

docker-compose.yml、.envに追記

最後にdocker-compose.ymlにMySQL用、phpMyAdmin用コンテナの記述を追記します。
設定値は環境変数として.envファイルに別記します。
phpMyAdminコンテナには接続するホスト情報を環境変数に書いておく必要があります。
※先述のとおり、個人的にはDocker上のphpMyAdminは使っていません。
phpMyAdminが不要であれば該当の箇所を取り除いても構築可能です。

# docker-compose.yml

version: '3'

services:
  web:
    container_name: docker-compose-mysql-web
    build: ./web
    ports:
      - '80:80'
    volumes:
      - ../html:/var/www/html
    hostname: localhost
    networks:
      - br0
  mysql:
    container_name: docker-compose-mysql-mysql
    build: ./db
    volumes:
      - ./db/mysql_data:/var/lib/mysql
    ports:
      - '${FORWARD_DB_PORT}:3306'
    hostname: localhost
    restart: always
    environment:
      # ユーザーアカウントとDBを設定
      MYSQL_DATABASE: '${DB_DATABASE}'
      MYSQL_USER: '${DB_USER}'
      MYSQL_PASSWORD: '${DB_PASSWORD}'
      MYSQL_HOST: '${DB_HOST}'
      MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
      MYSQL_ROOT_HOST: '%'
      TZ: '${TZ}'
    networks:
      - br0
  phpmyadmin:
    container_name: docker-compose-mysql-phpmyadmin
    image: phpmyadmin/phpmyadmin
    ports:
      - '${FORWARD_PMA_PORT}:80'
    restart: always
    environment:
      # mysqlにコンテナに接続
      PMA_HOST: '${DB_HOST}'
    networks:
      - br0

networks:
  br0:
    driver: bridge
# .env

COMPOSE_PROJECT_NAME=docker-compose-mysql
DB_HOST=mysql
DB_DATABASE=sample
DB_USER=docker
DB_PASSWORD=password
TZ=Asia/Tokyo
FORWARD_DB_PORT=3306
FORWARD_PMA_PORT=8081

ここまでの作業で、ファイル構成は以下となります。

# ファイル構成

├── docker
│   ├── .env
│   ├── docker-compose.yml
│   └── db
│       ├── Dockerfile
│       ├── my.cnf
│       └── mysql_data
│   └── web
│       └── Dockerfile
└── html

動作確認

phpMyAdminでログインできるか確認

http://localhost:8081/ にアクセスします。
「8080」は.envで設定したポート番号です。
ログイン画面では.envで設定したアカウントを入力します。
普通にログインできれば成功です。

phpMyAdminでサンプル用テーブルとレコードを作成

phpMyAdmin上で、設定した「sample」というデータベースを選択、下記のSQLを実行させてテーブルとレコードを作成します。

CREATE TABLE `items` (
  `id` int NOT NULL PRIMARY KEY,
  `name` text
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

INSERT INTO `items` (`id`, `name`) VALUES
(1, 'パソコン'),
(2, 'タブレット'),
(3, 'スマートフォン'),
(4, 'キーボード'),
(5, 'マウス');

phpファイルからデータベースにアクセスできるか確認

htmlディレクトリの直下にtest.phpというファイルを作成して確認します。
テーブルの内容を取得して出力するだけのプログラムです。

# test.php

<?php
// ドライバ呼び出しを使用して MySQL データベースに接続します
$dsn = 'mysql:dbname=sample;host=mysql';
$user = 'docker';
$password = 'password';

try {
    $dbh = new PDO($dsn, $user, $password);
    echo "接続成功\n";
} catch (PDOException $e) {
    echo "接続失敗: " . $e->getMessage() . "\n";
    exit(1);
}

$sql = 'SELECT * FROM items';
$sth = $dbh->prepare($sql);
$sth->execute();
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
var_dump($result);

http://localhost/test.php にアクセスしてみます。
下記のように出力されれば成功で、ひととおりの作業は完了です。

接続成功 array(5) { [0]=> array(2) { ["id"]=> string(1) "1" ["name"]=> string(12) "パソコン" } [1]=> array(2) { ["id"]=> string(1) "2" ["name"]=> string(15) "タブレット" } [2]=> array(2) { ["id"]=> string(1) "3" ["name"]=> string(21) "スマートフォン" } [3]=> array(2) { ["id"]=> string(1) "4" ["name"]=> string(15) "キーボード" } [4]=> array(2) { ["id"]=> string(1) "5" ["name"]=> string(9) "マウス" } } 

(参考)DB用コンテナでMySQLクライアントにログインできるか確認

※今回はこの作業がなくても動作確認は可能です。

DB用コンテナに入ってみます。
これは下記のコード例のように「docker exec〜」で行います。
コンテナに入ってからは「mysql -u docker -p」とコマンドを実行させて、パスワード(.envファイルに書いた値です。)を入力します。
ログインできれば成功です。
同様に「mysql -u root -p」と実行させてrootで入れるかも確認しておきましょう。

❯ docker exec -it docker-compose-mysql-mysql bash
root@localhost:/# mysql -u docker -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

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> 

Discussion