zukucode
主にWEB関連の情報を技術メモとして発信しています。

Docker Composeでphpでmysqlにアクセスする

Dockerで作成したphpのコンテナから別コンテナのmysqlにアクセスする方法を紹介します。

Docker ComposeでNginxとphpを連携するで作成した環境に対して修正を行っていきます。

mysqlの設定

mysqlのコンテナを作成します。

dbというサービス名で作成します。このサービス名は後ほど使用するため、覚えておいてください。

volumesmysqlのデータをマウントすることにより、コンテナを停止してもデータベースの内容を永続化しています。

また、他のコンテナと同様に、ホスト側で記載した設定ファイルをコンテナ側で読み込むようにしています。

ルートパスワードの設定とdocker_dbという名前でデータベースも作成しています。

また、appコンテナ(php)からdbコンテナを参照するため、appコンテナの設定のdepends_ondbを追加します。

docker-compose.yml
version: '3'
services:
  web:
    image: nginx
    depends_on:
      - app
    ports:
      - "8080:80"
    volumes:
      - ./docker/web/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html
  app:
    image: php:7-fpm
    depends_on:
      - db
    volumes:
      - ./docker/app/php.ini:/usr/local/etc/php/php.ini
      - .:/var/www/html
  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: docker_db
      MYSQL_USER: docker_user
      MYSQL_PASSWORD: docker_pass
    ports:
      - "3306:3306"
    volumes:
      - ./docker/db/data:/var/lib/mysql
      - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf

フォルダ構成は以下になります。(my.cnfのファイルの中身は空で問題ありません)

  • カレントディレクトリ
    • docker
      • web
        • default.conf
      • app
        • php.ini
      • db ←追加
        • data ←追加
        • my.cnf ←追加
    • docker-compose.yml
    • index.html
    • info.php

接続確認

phpで接続確認を行うためのファイルを作成します。

connect.php
<?php 
    try {
        // host=XXXの部分のXXXにはmysqlのサービス名を指定します
        $dsn = 'mysql:host=db;dbname=docker_db;';
        $db = new PDO($dsn, 'docker_user', 'docker_pass');

        $sql = 'SELECT version();';
        $stmt = $db->prepare($sql);
        $stmt->execute();
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
        var_dump($result);
    } catch (PDOException $e) {
        echo $e->getMessage();
        exit;
    }

コンテナを実行し、localhost:8080/connect.phpにアクセスすると「could not find driver」のエラーが発生します。

phpmysqlの接続に必要なモジュールがインストールされていないため、必要なモジュールをインストールするようにphpのイメージを修正します。

phpイメージの作成

ベースのイメージは今まで使用していたphp:7-fpmで、さらにmysqlの接続に必要なモジュールをインストールするように、DockerFileを作成します。

  • カレントディレクトリ
    • docker
      • web
        • default.conf
      • app
        • php.ini
        • DockerFile ←追加
      • db
        • data
        • my.cnf
    • docker-compose.yml
    • index.html
    • info.php
    • connect.php

以下の設定はphp:7-fpmのイメージをベースに、パッケージをアップデートして最新にしたあと、docker-php-ext-installpdo_mysqlのモジュールをインストールしています。

DockerFile
FROM php:7-fpm

RUN apt-get update \
    && docker-php-ext-install pdo_mysql

このDockerFileで作成したイメージを使用するように、docker-compose.ymlを修正します。

docker-compose.yml
  app:
    image: php:7-fpm
    depends_on:
      - db
    build: ./docker/app
    volumes:
      - ./docker/app/php.ini:/usr/local/etc/php/php.ini
      - .:/var/www/html

環境構築の最中はデータベースの設定情報などを初期化したいため、mysqlのコンテナを再起動するときは以下のコマンドで永続化したフォルダを削除してから起動するようにします。

$ sudo rm -rf docker/db/data

また、コンテナを起動直後にデータベースにアクセスすると以下のエラーになることがあります。

SQLSTATE[HY000] [2002] Connection refused

エラーが表示された場合は少し(30秒ほど)待ってから再度確認してみてください。

再度実行すると今度は以下のエラーが表示されます。

SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client

これはDockerの設定の問題というわけではなく、MySQLのバージョンが8以上の場合に、デフォルトの認証方法が変更されたことによるエラーです。

従来の認証方法にするため、MySQLの設定ファイルに以下を記載します。

my.conf
[mysqld]
default_authentication_plugin=mysql_native_password

再度アクセスするとSQLが実行され、MySQLへの接続ができていることが確認できます。

phpmyadminを導入する方法はDocker Composeでphpmyadminを導入するで紹介します。


関連記事