こんにちは。もんしょー(@sima199407)です。
という疑問があるかと思います。
今回は、docker上のmysqlとPHPの接続方法について解説してきたいと思います。
完成のソースコードも用意しておりますので、説明は省略したい方はこちらをどうぞ。
github
また、mysql+python編の記事もありますのでぜひ。
[box06 title="docker関連記事"]docker上で立てたMySQLとpythonの接続方法【sequel Proの接続方法も解説】[/box06]
開発環境
・Mac OS Mojave
・docker for Mac
・MySQL 5.7
・PHP7.1
上記の通りです。
dockerのインストール方法は下記からDLしていただければオッケーです。
docker-php-mysql/
├── mysql
│ ├── Dockerfile
│ ├── docker-compose.yaml
│ └── my.cnf
└── nginx-php
├── Dockerfile
├── default.conf
├── docker-compose.yml
└── php
└── index.php
docker-compseファイルを作成
今回はdocker-composeを使って作業していきます。
通常であれば1つのdocker-composeファイルにmysqlとphpを書いていくのですが、今回は別々に作成されたものをつなげていく作業をやっていこうと思うので別々で書いていきます。
mysql/docker-compose.yml
コードは以下の通り
version: '3'
services:
mysql:
image: mysql:5.7
container_name: mysql
ports:
- "3316:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: mysql
MYSQL_PASSWORD: mysql
MYSQL_DATABASE: mysql
volumes:
- ./my.cnf:/etc/mysql/conf.d/my.cnf
volumes_from: #may not require
- mysql-volume:rw #may not require
working_dir: "/var/lib/mysql"
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
depends_on:
- mysql-volume
mysql-volume:
image: busybox
container_name: mysql-volume
volumes:
- ./data:/var/lib/mysql
nginx-php/docker-compose.yml
コードは以下の通り
version: '3'
services:
web:
container_name: nginx-alpine
image: nginx:1.13.5-alpine
ports:
- "88:80"
depends_on:
- app
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
- ./data/html:/var/www/html
app:
container_name: php-alpine
build: ./php
volumes:
- ./data/html:/var/www/html
web→nginx
app→php
になります。
docker-composeでコンテナを作成するときにimageかbuildで作成するかと思いますが、phpの方はDockerfileを参照するのでbuildに書いていきます。
DockerFileを作成
mysql/Dockerfile
コードは以下の通り
FROM mysql:5.7
RUN touch /var/log/mysql/mysqld.log
FROM alpine:latest
RUN apk update && \
apk add mysql-client
nginx-php/Dockerfile
コードは以下の通り
FROM php:7.1-fpm
RUN docker-php-ext-install pdo_mysql ###ポイント
2行目のコマンドが重要でして、デフォルトだと入っていないmysqlのドライバーをインストールしています。これを入れていないとエラーがでて接続ができません。(ここでハマりました。。)
.confファイルの作成
各コンテナの詳細な設定ファイルになります。
ここが抜けると後々に支障をきたす場合がございますので作成することをおすすめします。
php/default.conf
コードは以下の通り
server {
listen 80;
server_name _;
root /var/www/html;
index index.php;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(\.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
imageだけでいいかなと思って作業していたら、cssとjsを読み込んでくれないというエラーが出てきたので、こちらを入れてコンテナを再度立ち上げたところ、その事象を解決できたので入れておきましょう。
mysql/my.cnf
コードは以下の通り
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
[client]
default-character-set=utf8
mysqlの設定内容です。
コンテナ作るときに設定しておくと便利なので書いておきます。
コンテナ生成〜コンテナ同士の接続まで
srcディレクトリを除くファイルが出来上がったので、ここからコマンドを叩いていきます。
phpとnginxのコンテナを立ち上げる
以下のコマンドを叩きます。
$ cd nginx-php
$ docker-compose up -d --build
無事に立ち上がっているか確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4444eree4444 nginx:1.13.5-alpine "nginx -g 'daemon of…" 27 hours ago Up 27 hours 0.0.0.0:88->80/tcp nginx-alpine
333wwwww3333 nginx-php_app "docker-php-entrypoi…" 27 hours ago Up 27 hours 9000/tcp php-alpine
mysqlのコンテナを立ち上げる
先ほどと同じようにmysqlのコンテナを立てますので、以下のコマンドを叩きます。
$ cd mysql
$ docker-compose up -d --build
そしてmysqlコンテナが立ち上がっている確認します
$ docker ps
395a5936t080 mysql:5.7 "docker-entrypoint.s…" 2 days ago Up 2 days 33060/tcp, 0.0.0.0:3316->3306/tcp mysql
mysqlのhostを探す
dockerの場合、mysqlに接続するためのゲートウェイとなるホストIPアドレスを調べる必要があります。
以下の方法で調べることができます。
mysqlのコンテナに入る
ターミナルで作業します
$ docker exec -it [コンテナ名(例)mysql] sh
#
コンテナ名の代わりにコンテナIDを使うこともできます。
ユーザー権限を変える
# mysql -u root -p //rootでmysqlにログイン
Enter password:[docker-compose.ymlで設定したrootのパスワード]
mysql> GRANT ALL PRIVILEGES ON *.* TO mysql@'%';
テストデータを入れる
まずテストテーブルを作成
mysql> CREATE TABLE test_users (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL,
email VARCHAR(32) NOT NULL,
PRIMARY KEY (id)
);
そして、テストデータを入れます
mysql> INSERT INTO test_users (id,name,email) VALUES (1, 'taro','taro@test.com');
jqをインストール
jqとは、JSONでデータを使うコマンドです。
ターミナルで以下を叩きます。
$ brew install jq
MySQLコンテナのネットワークを調べます。
$ docker inspect mysql | jq '.[0].NetworkSettings.Networks|keys'
[
"mysql_default"
]
mysql_defaultとわかったので、以下のコマンドを叩きます。
$ docker network inspect mysql_default | jq '.[0].IPAM.Config[0].Gateway'
"172.22.3.1"
上記が設定するべきIPアドレスになります。
src/index.phpを作成
接続がうまく行っているかを確認するため、index.phpを作ります。
<?php
//接続する設定を作成
$dsn = 'mysql:dbname=mysql;host=172.22.3.1;port=3316';
$user = 'mysql';
$password = 'mysql';
try {
$dbh = new PDO($dsn, $user, $password);
$sql = "SELECT * FROM test_users";
$stmt = $dbh -> query($sql);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if (isset($result)){
var_dump($result);
}
} catch (PDOException $e) {
echo "接続失敗: " . $e->getMessage() . "\n";
exit();
}
$dsnのhostの部分は先程jqを使って調べたIPアドレスを入れます。
接続してみる
http://localhost:88
に接続して、mysqlに入れたテストデータが入っていればOKです。
エラーが出るとき
index.phpに以下を追記してください
<?php
phpinfo();
~
それでlocalhostにアクセスすると、PHPの情報が入っているので、「PDO」の欄を見てください。
その中に「mysql」が入っている確認してみてください。
もし、ない場合はDockerfileで設定した「docker-php-ext-install pdo_mysql」がインストールされていないようなので、もう一度ファイルを見直しましょう。
まとめ
dockerは便利ですが、環境設定をするときに少々ハマってしまうことがあるので参考になればと思います。
今回の場合ですと、phpにmysqlのドライバーが入っていないと接続できないというのがキーになってくるかと思いますのでまずそこを疑ってみるのが良さそうです。