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

↑ この部分。