64
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

docker-compose を用いて Apache・PHP・MySQL の開発環境を構築してみた

Last updated at Posted at 2020-08-13

はじめに

docker-compose を用いて Apache・PHP・MySQL の開発環境を構築してみた備忘録になります。

構成図

ddd.png

GitHub にもあげました。ご参考まで。

できたこと

以下を自動化する docker-compose の開発環境構築を行いました。

  • DocumentRoot の変更
  • php.ini の変更
  • my.cnf の変更
  • MySQL への初期データの投入
  • MySQL のデータの永続化
  • PHP-Apache コンテナから MySQL コンテナへの疎通

つまり、これらの環境がワンライナーで構築できるようになりました。

バージョン情報

docker-compose はインストールされていることが前提になります。
今回は以下のバージョンでの動きになります。

$ docker-compose -v
docker-compose version 1.26.2, build eefe0d31

PHP のバージョンは 5.4、MySQL のバージョンは 5.5 の環境を構築します。
Apache のバージョンは特に気にしていません。

ディレクトリ構造

ディレクトリ構造は以下のようになります。

.
├── config
│   ├── mysql
│   │   ├── Dockerfile
│   │   ├── initdb.d
│   │   │   └── init.sql
│   │   └── my.cnf
│   └── php
│       ├── Dockerfile
│       ├── apache2.conf
│       ├── php.ini
│       └── sites
│           ├── 000-default.conf
│           └── default-ssl.conf
├── data
├── docker-compose.yml
└── html
    └── test
        ├── connect.php
        └── index.php

設定

各サービスに以下のような設定ファイルがそれぞれあると思いますが、それらを変更したものを動かしたいと思います。

Apache の設定

今回は DocumentRoot を変更してみます。

公式ドキュメント をみると以下のように Dockerfile を記述することで DocumentRoot を変更できるようです。

b.png

いろいろな記事をみるとコンテナから 000-default.conf などの設定ファイルをホスト側にもってきてそれを修正した後、Dockerfile の COPY でコンテナ側にコピーするようでした。

やはり公式ドキュメントをみるのが一番ですね。

公式ドキュメントのように行ったらコンテナが再起動ループに陥ってしまいました。

※ 理由をよく調べたら php:5.5-apache 以降であればそれでよかったらしいです。

なので、php:5.4-apache のイメージからコンテナを立ち上げて、元ファイルをホスト側にコピーして、それを編集することにしました。

# とりあえず php:5.4-apache のコンテナを動かしてログインする
$ docker image pull php:5.4-apache
$ docker container run --name php54apache -d php:5.4-apache
$ docker exec -it php54apache /bin/bash

# 設定ファイルを確認 ( php:5.4-apache 以前は apache2.conf の修正も必要)
$ ls /etc/apache2/apache2.conf
httpd.conf

$ ls /etc/apache2/sites-available
000-default.conf  default-ssl.conf

# コンテナを抜ける
$ exit

# ホスト側にコピー
$ docker container cp php54apache:/etc/apache2/apache2.conf ./config/php
$ docker container cp php54apache:/etc/apache2/sites-available/000-default.conf ./config/php/sites
$ docker container cp php54apache:/etc/apache2/sites-available/default-ssl.conf ./config/php/sites

これらの apache2.conf000-default.confdefault-ssl.conf に記述してある DocumentRoot を変更します。

今回は以下のように変更しました。

# DocumentRoot /var/www/html
DocumentRoot /var/www/html/test

これで DocumentRoot の変更の準備は完了です。

PHP の設定

PHP は php.ini によって設定を行います。

公式ドキュメント をみると以下のように記述することで php.ini を指定するらしいです。

a.png

しかし、コンテナを立ち上げてログインしてみても、 php.ini-developmentphp.ini-produciton のようなファイルは存在しませんでした。

おそらく Apache の設定でもそうであったように公式のドキュメントは過去のバージョンまで挙動は保証していないようです。

サンプルにあるような php:7.4-fpm-alpine ならそれで良さそうですね。

今回は php.ini-developmentphp.ini-produciton については GitHub で公開してあったのでそちらの php.ini-development を元に php.ini を作成することにしました。

php.ini の修正についてはこちらを参照して、ロケーションや言語の設定を修正しました。

MySQL の設定ファイルの変更

MySQL の設定ファイルは my.cnf によって行います。

MySQL の設定ファイルの my.cnf は 公式ドキュメント によると /etc/mysql/my.cnf に配置してあるとのことでした。

c.png

なのでそちらをローカルホストに持ってきて、適宜修正していきたいと思います。

# とりあえず mysql:5.5 のコンテナを動かしてログインする
$ docker image pull mysql:5.5
$ docker container run -e MYSQL_ROOT_PASSWORD=sample_pw --name mysql55 -d mysql:5.5
$ docker exec -it mysql55 /bin/bash

# /etc/mysql/my.cnf を確認
$ ls /etc/mysql/my.cnf
/etc/mysql/my.cnf

# コンテナを抜ける
$ exit

# my.cnf をホスト側にコピー
$ docker container cp mysql55:/etc/mysql/my.cnf ./config/mysql/

あとは環境に合わせて修正して、my.cnf を作成してください。

※ ちなみに今回は my.cnf の修正は行っていません。

Dockerfile の作成

Dockerfile は php:5.4-apachemysql:5.5 のイメージについて作成しました。

php:5.4-apache

config/php/Dockerfile
# image
FROM php:5.4-apache

# Set php.ini
COPY ./php.ini /usr/local/etc/php/

# Set apache conf (Before tag:5.4-apache)
COPY ./apache2.conf /etc/apache2/
COPY ./sites/*.conf /etc/apache2/sites-available/

# Set apache conf (After tag:5.5-apache)
# ENV APACHE_DOCUMENT_ROOT /var/www/html/test
# RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
# RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

# Install MySQL connection module
RUN apt-get update \
  && apt-get install -y libpq-dev \
  && docker-php-ext-install pdo_mysql pdo_pgsql mysqli mbstring

ここでは「DocumentRoot の変更」、「php.ini の配置」、「MySQL と疎通するためのモジュールを追加」しています。

mysql:5.5

config/mysql/Dockerfile
# image
FROM mysql:5.5

# Set my.cnf
COPY ./my.cnf /etc/mysql/conf.d/

# Set Japanese
RUN apt-get update && apt-get install -y \
  locales \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*
RUN sed -i -E 's/# (ja_JP.UTF-8)/\1/' /etc/locale.gen \
  && locale-gen
ENV LANG ja_JP.UTF-8
CMD ["mysqld", "--character-set-server=utf8", "--collation-server=utf8_unicode_ci"]

デフォルトのままであると MySQL にログインした後に日本語の入力ができなかったため、ここでは日本語を入力可能にするような設定をおこなています。

MySQL の日本語の設定は こちら を参照しました。

MySQL の初期データの投入

docker-compose 起動時に MySQL に初期データを投入してみたく、以下のような SQL を用意しました。

init.sql
DROP TABLE IF EXISTS sample_table;

CREATE TABLE sample_table (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name TEXT NOT NULL
) charset=utf8;

INSERT INTO sample_table (name) VALUES ("太郎"),("花子"),("令和");

コンテナ起動後にここで記述した SQL が実行されていることを確認します。

docker-compose.yml の作成

以下のように docker-compose.yml を作成しました。

docker-compose.yml
version: '3.8'

services:

  # PHP Apache
  php-apache:
    build: ./config/php
    ports:
      - "8080:80"
    volumes:
      - ./html:/var/www/html
    restart: always
    depends_on:
      - mysql

  # MySQL
  mysql:
    build: ./config/mysql
    ports:
      - 3306:3306
    volumes:
      - ./config/mysql/initdb.d:/docker-entrypoint-initdb.d
      - ./data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: sample_root_passward
      MYSQL_DATABASE: sample_db
      MYSQL_USER: sample_user
      MYSQL_PASSWORD: sample_pass

MySQL のデータの永続化について

MySQL のデータディレクトリは /var/lib/mysql であり、 - ./data:/var/lib/mysql とあるようにホスト側の ./data ディレクトリにマウントすることによってデータを永続化しております。

試してみたところ docker-compose stopdocker-compose down してもデータが永続化されていることが確認できました。

docker-compose 使い方

いよいよ docker-compose を動かします。

docker-compose 起動

まずはなにも起動されていないことを確認します。

$ docker-compose ps
Name   Command   State   Ports
------------------------------

$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

今回はわかりやすいようにコンテナも空の状態にしておきます。

docker-compose.yml が存在する階層で docker-compose up -d コマンドを実行することで、docker-compose.yml の記述をもとにコンテナが作成されます。

※ docker-compose のコマンドの buildup の違いやオプションについてはこちらがわかりやすかったです。

# image の作成
$ docker-compose build --no-cache
Successfully tagged docker-compose-sample_php-apache:latest

# コンテナの構築・起動
$ docker-compose up -d
Creating network "docker-compose-sample_default" with the default driver
Creating docker-compose-sample_mysql_1 ... done
Creating docker-compose-sample_php-apache_1 ... done

# docker-compose の確認
$ docker-compose ps
               Name                            Command             State           Ports
-------------------------------------------------------------------------------------------------
docker-compose-sample_mysql_1        docker-entrypoint.sh mysqld   Up      0.0.0.0:3306->3306/tcp
docker-compose-sample_php-apache_1   apache2-foreground            Up      0.0.0.0:8080->80/tcp

# コンテナの確認
$ docker container ls
CONTAINER ID        IMAGE                              COMMAND                  CREATED             STATUS              PORTS                    NAMES
26b0cec2daad        docker-compose-sample_php-apache   "apache2-foreground"     3 minutes ago       Up 3 minutes        0.0.0.0:8080->80/tcp     docker-compose-sample_php-apache_1
eaae044f4bba        mysql:5.5                          "docker-entrypoint.s…"   3 minutes ago       Up 3 minutes        0.0.0.0:3306->3306/tcp   docker-compose-sample_mysql_1

コンテナが動いていることが確認できました。

PHP-Apache コンテナの確認

DocumentRoot の直下に配置する、php:5.4-apache コンテナの疎通確認用のページとして以下のようなファイルを用意しました。

html/test/index.php
<?php
echo  __DIR__;
phpinfo();

http://localhost:8080 にアクセスすると以下のように表示されるはずです。

echo __DIR__; はその PHP ファイルが置かれている絶対パスを出力するので DocumentRoot の変更が行われていることが確認できます。

また、php.ini についてオリジナルものから修正を加えていれば、phpinfo(); の出力でそちらも反映されていることも確認できるかと思います。

f.png

MySQL コンテナの確認

mysql:5.5 のイメージで作成されたコンテナにログインして、初期データが投入されていることを確認します。

shell
# コンテナにログイン
$ docker exec -it eaae044f4bba /bin/bash

# MySQL にログイン
$ mysql -p
Enter password:

パスワードを求められるので docker-compose.yml で MYSQL_ROOT_PASSWORD の環境変数に登録した sample_root_passward と入力するとログインできます。

docker-compose.yml に登録した MYSQL_DATABASEMYSQL_USER が登録されていることを確認します。

mysql> select user, host from mysql.user;

+-------------+-----------+
| user        | host      |
+-------------+-----------+
| root        | %         |
| sample_user | %         |
| root        | localhost |
+-------------+-----------+
3 rows in set (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sample_db          |
+--------------------+
4 rows in set (0.00 sec)

sample_usersample_db があることが確認できました。

続いて init.sql で作成したテーブルとカラムについても確認してみます。

mysql> use sample_db;
Database changed

mysql> show tables;
+---------------------+
| Tables_in_sample_db |
+---------------------+
| sample_table        |
+---------------------+
1 row in set (0.00 sec)

mysql> select * from sample_table;
+----+--------+
| id | name   |
+----+--------+
|  1 | 太郎 |
|  2 | 花子 |
|  3 | 令和 |
+----+--------+
3 rows in set (0.00 sec)

テーブルとカラムについても問題なく確認できました。

PHP-Apache から MySQL コンテナへの疎通確認

PHP-Apache から MySQL コンテナへの疎通確認用のページとして以下のようなファイルを用意しました。

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

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

※ 注意点として、ホスト名は localhost127.0.0.1 ではなく、docker-compose.yml でサービス名として指定してた mysql を使用します。

http://localhost:8080/connect.php にアクセスすると以下のように表示されればが PHP-Apache から MySQL コンテナへの疎通がうまく行っています。

g.png さきほど、初期投入されたデータが確認できますね。

docker-compose 停止・削除

以下のコマンドで 停止・削除 を行います。

# コンテナを停止
$ docker-compose stop

# コンテナを停止し、そのコンテナとネットワークの削除
$ docker-compose down

# コンテナを停止し、そのコンテナとネットワークを削除、さらにイメージも削除
$ docker-compose down --rmi all --volumes

./config/mysql/initdb.d/init.sql の初期データ投入からやり直したい時などは docker-compose down --rmi all --volumes してから ./data ディレクトリの中身も削除して docker-compose up -d でコンテナの構築・起動からやり直してください。

まとめ

以下を自動化する docker-compose の開発環境構築を行いました。

  • DocumentRoot の変更
  • php.ini の変更
  • my.cnf の変更
  • MySQL への初期データの投入
  • MySQL のデータの永続化
  • PHP-Apache コンテナから MySQL コンテナへの疎通

つまり、これらの環境がワンライナーで構築できるようになりました。

学んだこと

今回初めて docker-compose で開発環境を構築してみて学んだことを羅列します。

  • 公式ドキュメント(DockerHub)は読んだ方がいい
    • Qiita よりも DockerHub を先に見た方がよさそうです。
  • docker-compose.yml と Dockerfile は書き分ける
    • 一度変更すればコンテナ起動後に変更のない設定ファイルなどは Dockerfile で COPY でコンテナ側にファイルを配置して、コンテナ起動後に変更のあるものは docker-compose.yml でマウントさせるという書き分けがよさそうです。
  • Dockerfile をいきなり書くのは難しい
    • 以下の手順で Dockerfile を書くと良いです。
      • ベースイメージを決める
      • ベースイメージのコンテナ内で作業しつつ、うまくいった処理をメモ
      • 全て成功したらDockerfileを作成

以上になります。

64
56
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
64
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?