Docker Composeを使ってphpからMySQLに接続する環境を作る(Apple Silicon arm64)
M2 MacBook Airに乗り換えてから
Docker Composeを使ってphpからMySQL/MariaDBに接続する環境を作る
でDocker環境を構築したのですが、コンテナは起動したもののMySQLへの接続が上手くいきませんでした。
Host '192.168.0.1' is not allowed to connect to this MariaDB server
Apple Silicon arm64に対応できるよう内容を見直しました。
前提
- httpのコンテナだけを構築していて、phpのみインストールされている状態です。
- httpコンテナは「Dockerfile」を使ってビルドします。
- htmlファイルはホスト環境にあるものをバインドマウントで永続化しています。
- 追加するDB用コンテナのデータはバインドマウントで永続化します。
具体的には以下のファイル構成/内容です。
最低限ではありませんが、それに近い内容です。
ここからDB接続もできるようにしていきます。
M2 MacBook Airで動作確認していますがApple Silicon arm64であれば動くと思います。
# ファイル構成
├── docker
│ ├── docker-compose.yml
│ └── web
│ └── Dockerfile
└── html
手順(MySQLコンテナを追加して連携)
データディレクトリを用意
データの永続化です。
コンテナを削除してもデータが消えないようにデータディレクトリを用意します。
ディレクトリの名前は何でもよいです。
ここでは「mysql_data」としました。
後でdocker-compose.ymlに追記します。
# ファイル構成
├── docker
│ ├── docker-compose.yml
│ └── db
│ └── mysql_data
│ └── web
│ └── Dockerfile
└── html
docker-compose.yml、.envに追記
最後にdocker-compose.ymlにMySQL用、phpMyAdmin用コンテナの記述を追記します。
設定値は環境変数として.envファイルに別記します。
phpMyAdminコンテナには接続するホスト情報を環境変数に書いておく必要があります。
※先述のとおり、個人的にはDocker上のphpMyAdminは使っていません。
phpMyAdminが不要であればdocker-compose.ymlや.envにある該当箇所を取り除いても構築可能です。
# 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
image: 'mysql:8'
# image: 'arm64v8/mysql'
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
command: --default-authentication-plugin=mysql_native_password --sort_buffer_size=1073741824
phpmyadmin:
container_name: docker-compose-mysql-phpmyadmin
image: phpmyadmin/phpmyadmin
ports:
- '${FORWARD_PMA_PORT}:80'
restart: always
environment:
# mysqlにコンテナに接続
PMA_HOST: '${MYSQL_HOST}'
networks:
- br0
networks:
br0:
driver: bridge
※「command」の値は一例です。バージョンなどの構成によって適宜変更します。
- default-authentication-plugin: MySQL8から認証プラグインが変更になった関係で、DB接続できるようにするために記載。
- sort_buffer_size: ソート(ORDER BYなど)に関わる処理が実行される場合のメモリ割り当て。標準のままでは頻繁に動作しなくなるのである程度上げる場合に。(余談ですが、Laravelで開発するときにこの割当をしていないせいでしょっちゅう動かなくなるような。。)
- collation-server: 照合順序。MySQL8からデフォルトがutf8mb4になりました。明示的に指定する場合に記述(php5.6以下の場合はこれを指定する必要があります。)
- character-set-server=utf8: 文字エンコーディング。MySQL8からデフォルトがutf8mb4になりました。明示的に指定する場合に記述(php5.6以下の場合はこれを指定する必要があります。)
command: --collation-server=utf8_unicode_ci --character-set-server=utf8 --default-authentication-plugin=mysql_native_password --sort_buffer_size=1073741824
追記(2023/08/17): imageの指定は現在「arm64v8/mysql」ではなく「mysql:8」で接続できました。
# .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
│ └── mysql_data
│ └── web
│ └── Dockerfile
└── html
動作確認
phpMyAdminでログインできるか確認
http://localhost:8081/ にアクセスします。
「8081」は.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