docker-composeでPHPとMySQLを連動させる

参考：https://qiita.com/fujitak/items/b56122e2ecd94022a7b6
（参考にさせていただきました！ありがとうございました！）

##カスタムネットワークの作成
```
$ docker network create phm
```
「phm」は任意の名前

###確認
```
$ docker network ls
```

##ディレクトリ構成を決める

```
├── docker-compose.yml
├── index.php
├── mysql
│   ├── Dockerfile
│   ├── mysql_conf
│       └── custom.cnf
├── php
    └── Dockerfile
```
以下の記事では作業ディレクトリは
`/var/www/docker/php-mysql`
の前提で記述する。

##Dockerfileの作成

###php/Dockerfile
```
FROM php:7.2-apache
RUN apt-get update && \
  docker-php-ext-install pdo_mysql mysqli #(*1)

WORKDIR /var/www/docker/php-mysql

EXPOSE 80
```
(*1)元記事ではmbstringもインストールするように設定されていたが、すでに入っているということでエラーになる。

###mysql/Dockerfile
```
FROM mysql:8.0
```

###docker-compose.yml
```
version: "3"
services:
  app:
    container_name: php
    build:
      context: ./php
      dockerfile: Dockerfile
    tty: true
    volumes:
      - .:/var/www/html #(※2)
    ports:
      - "8000:80" #(※3)
    network_mode: "phm"

  db1:
    container_name: mysql
    build:
      context: ./mysql
      dockerfile: Dockerfile
    environment:
      - MYSQL_ROOT_PASSWORD=pass
    volumes:
      - ./mysql/mysql_conf:/etc/mysql/conf.d #(※4)
    network_mode: "phm"

networks:
  phm:
```
(※2) docker-compose.ymlのあるディレクトリが、コンテナ側の/var/www/htmlにマウントされる。
(※3) 元記事では「80:80」となっていたが、ホスト側にapacheなどが入っていて80番ポートを使っているとエラーになるので変更する。
(※4) mysqlの設定ファイルを置くディレクトリに注意。

##MySQLの設定ファイルを書く
MySQL8ではデフォルトの認証方式が「caching_sha2_password」であり

```
The server requested authentication method unknown to the client
```
というエラーが発生するので、認証方式を「mysql_native_password」に変更しておく。
###mysql/mysql_conf/custom.cnf

```
[mysqld]
default_authentication_plugin=mysql_native_password
```
##docker-composeを実行

```
/var/www/docker/php-mysql
```

に戻ってから、(戻らなくても大丈夫だが、どこのymlが実行されるのか未調査)

```
$ docker-compose up -d
```
を実行

##imageの確認

```
$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE 
php-mysql_app       latest              e46f7f57f545        About a minute ago   428MB
php                 7.2-apache          fc63b5c72cff        4 days ago           410MB
mysql               8.0                 9228ee8bac7a        4 days ago           547MB
php-mysql_db1       latest              9228ee8bac7a        4 days ago           547MB
```

##containerの確認
```
$ docker ps -a

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
4aa3317e2d9e        php-mysql_app       "docker-php-entrypoi…"   2 minutes ago       Up 2 minutes        0.0.0.0:8000->80/tcp   php
8712548172e8        php-mysql_db1       "docker-entrypoint.s…"   2 minutes ago       Up 2 minutes        3306/tcp, 33060/tcp    mysql
```

##確認用スクリプト

###index.php

```
<meta charset="UTF-8">
<title>テスト</title>
<?php
    try {
        # hostには「docker-compose.yml」で指定したコンテナ名を記載
        $dsn = "mysql:host=mysql;dbname=sample;";
        $db = new PDO($dsn, 'root', 'pass');

        $sql = "SELECT * FROM test";
        $stmt = $db->prepare($sql);
        $stmt->execute();
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
        var_dump($result);
    } catch (PDOException $e) {
        echo $e->getMessage();
        exit;
    }
```

##DBエラーを承知でアクセスしてみる
```
$ curl http://localhost:8000/
```
```
<meta charset="UTF-8">
<title>テスト</title>
SQLSTATE[HY000] [1049] Unknown database 'sample'[someone@hoge php-mysql]$ 
```
DBの問い合わせまでうまく行っている

##MySQL側の設定

コンテナに入る

```
$ docker exec -it mysql bash
```
###MySQLへ接続
```
# mysql -u root -p
```
```
Enter password: 
```
で「pass」と入力。（docker-compose.ymlの「db1」の「environment」で設定）

## ユーザーの確認
```
select user,host from mysql.user;
```
```
root@localhost
```
が存在していたら削除(しないと、そっちが優先されて接続できない)

```
drop user root@localhost;
```

## 適当なデータベースとテーブルを作成
```
mysql> CREATE DATABASE sample;
mysql> USE sample;
mysql> CREATE TABLE test(id int AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255));
mysql> INSERT INTO test (name) VALUES ('John');
```
##再びアクセスしてみる
```
$ curl http://localhost:8000/
```
```
<meta charset="UTF-8">
<title>テスト</title>
array(1) {
  [0]=>
  array(2) {
    ["id"]=>
    string(1) "1"
    ["name"]=>
    string(4) "John"
  }
}
```
成功。

##(余談)ちなみに、phpコンテナに入ってみる
```
$ docker exec -it php bash
```
```
# cd /var/www/html
# ls
docker-compose.yml  index.php  mysql  php  php-mysql
```
と出て、docker-compose.yml で設定したvolumesの通りマウントされていることがわかる

```
    volumes:
      - .:/var/www/html
```
↑ この部分。