Docker ComposeでLAMP環境構築
この記事は今までのDocker系記事のゴール地点になる位置づけになります。(まだまだ怪しいところたくさんあるけれど...)
Dockerは初めて、という方は以下の記事を順に追う形で読まれていくとぼんやりとイメージが湧いてくるんじゃないかと思います。
ところどころに我流な点があるかと思いますがご容赦下さい。
環境
- Docker for mac
- Docker version 17.09.0-ce, build afdb6d4
- docker-compose version 1.16.1, build 6d1ac21
Docker composeとは
複数のコンテナを連携して開発ができるコマンド。
すごく便利。
ディレクトリ構成
作業用ディレクトリを下のような構成にします。
- docker-compose.yml - php - Dockerfile - php.ini - html - database.php - fetchTester.php - index.php
docker-compose.yml
version: '3' services: mysql: container_name: mysql_comp_test image: mysql:5.7 ports: - 3333:3306 environment: MYSQL_ROOT_PASSWORD: password volumes: - db:/var/lib/mysql phpmyadmin: container_name: phpmyadmin_comp_test image: phpmyadmin/phpmyadmin environment: - PMA_ARBITRARY=1 - PMA_HOST=mysql - PMA_USER=root - PMA_PASSWORD=password links: - mysql ports: - 8080:80 volumes: - /sessions php: container_name: php_apache_comp_test build: ./php ports: - 8000:80 volumes: - ./html:/var/www/html depends_on: - mysql volumes: db:
いらない記述などがあるような気がしますが、今回はとりあえずこれで済ませます。解説は後でします。
php/Dockerfile
FROM php:7-apache COPY php.ini /usr/local/etc/php/ RUN apt-get update \ && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng12-dev libmcrypt-dev \ && docker-php-ext-install pdo_mysql mysqli mbstring gd iconv mcrypt
php/php.ini
[Date] date.timezone = "Asia/Tokyo" [mbstring] mbstring.internal_encoding = "UTF-8" mbstring.language = "Japanese"
html/index.php
<?php require_once 'fetchTester.php'; $fetchtester = new FetchTester(); $fetchtester->fetch("testtable"); // 引数:テーブル名
html/fetchTester.php
<?php require_once 'database.php'; class FetchTester { private $pdo; function __construct() { $this->pdo = Database::connectDB(); } public function fetch($table) { $stmt = $this->selectTable($table); while($row = $stmt->fetch()) { var_dump($row); } } private function selectTable($table) { $sql = 'SELECT * FROM ' . $table; $stmt = $this->pdo->query($sql); return $stmt; } }
html/database.php
<?php class Database { public static function connectDB() { $pdo = ''; try { $pdo = new PDO( // mysqlコンテナ側のIPアドレスを入れてやらないといけない 'mysql:dbname=sample;host=xxx.xx.x.x;charset=utf8;', 'root', 'password', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ] ); } catch (PDOException $e) { header('Content-Type: text/plain; charset=UTF-8', true, 500); exit($e->getMessage()); } return $pdo; } }
html
ディレクトリ下のファイルはすべて、以前記事にした PDOのfetch系メソッド のものを再利用しています。
docekr-compose.yml
1. version
シンタックスバージョンです。現時点では3が最新。
2. services
この配下にある設定を1つのサービス(コンテナ)として認識します。 この配下にサービスを複数書いていく形になります。
3. container_name
コンテナの名称を設定。記述しない場合はサービス名などから自動的につくられますが、この名前がやたら長いものになったりならなかったり。
4. image
このイメージをもとにコンテナを作成します。イメージがなければプルしてきます。
5. ports
ホスト側のポート:コンテナ側のポートとすることで、ホスト側で指定したポート番号でアクセスできるようになります。
6. environment
コンテナを起動する際に渡す環境変数を設定します。この単語のスペルをenviroment
書いて何度もビルドエラーを起こしたのは内緒の話。
7. volumes
ホスト側パス:コンテナ側パスで、ホストのディレクトリをコンテナにボリュームとしてマウントすることができます。
8. build
任意のディレクトリ下のファイルをビルドします。ここでは./php
下をビルドする、という指示になります。
9. link、depends_on
コンテナをほかのサービスとリンクさせます。サービス名:エイリアス名でサービス名とリンク用エイリアスの両方を指定できます。
ビルド、ラン
docker-compose up -d
でビルドしつつ起動させます。 -d
でバックグラウンドでの起動となります。
処理が終了したらdocker-compose ps
で状態をチェックします。
Name Command State Ports -------------------------------------------------------------------------------------- mysql_comp_test docker-entrypoint.sh mysqld Up 0.0.0.0:3333->3306/tcp php_apache_comp_test docker-php-entrypoint apac ... Up 0.0.0.0:8000->80/tcp phpmyadmin_comp_test /run.sh phpmyadmin Up 0.0.0.0:8080->80/tcp
docker ps -a
でどうなるかも見てみます。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 783bdf5eb792 phpmyadmin/phpmyadmin "/run.sh phpmyadmin" 4 minutes ago Up 4 minutes 0.0.0.0:8080->80/tcp phpmyadmin_comp_test 9db98d802fc7 dockerlamp_php "docker-php-entryp..." 4 minutes ago Up 4 minutes 0.0.0.0:8000->80/tcp php_apache_comp_test 13655efc377f mysql:5.7 "docker-entrypoint..." 4 minutes ago Up 4 minutes 0.0.0.0:3333->3306/tcp mysql_comp_test
最初に見るべきはState
とSTATUS
です。Up
となっているでしょうか。
次にPorts
とPORTS
。docker-compose.yml
に書いたとおりにポートフォワーディングされていれば成功です。
DBセットアップ
まず、やらなくてはいけないのが、MySQLのコンテナのIPアドレスを調べることです。
docker exec -it mysql_comp_test /bin/bash
でコンテナに入って
hostname -i
でIPアドレスを確認できます。
確認したらexit
でホストマシンへ戻ってきます。
database.php
のhost=
の部分に確認したIPアドレスを入力します。
// mysqlコンテナ側のIPアドレスを入れてやらないといけない 'mysql:dbname=sample;host=xxx.xx.x.x;charset=utf8;',
続いてデータベースとテーブルを作成します。
phpMyAdminにhttp://localhost:8080
でアクセスできます。コンテナに入って、コマンド処理で作業しても良いのですが、やはり面倒ですよね。
sample
というデータベース (utf8_general_ci)
をつくって、その中に、testtable
というテーブルを作成します。データを適当に入れておきましょう。
CREATE TABLE `testtable` ( `id` int NOT NULL PRIMARY KEY AUTO_INCREMENT, `name` varchar(10) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8
いよいよhttp://localhost:8000
へアクセスしてみます。
array(2) { ["id"]=> string(1) "1" ["name"]=> string(4) "hoge" } array(2) { ["id"]=> string(1) "2" ["name"]=> string(8) "hogehoge" }
こんなふうにデータがダンプされれば成功です。
データが永続化されているか
docker-compose down
で立ち上げたコンテナ群を終了させることができます。
今度はオプション-d
を外してdocker-compose up
で起動をしてみましょう。こうすることでdocker-compose down
と打って終了する手間が省けるといえば省けます。
http://localhost:8000
やhttp://localhost:8080
にアクセスすると、先ほどと同じ出力がされるはずです。DBのデータが消滅していないことがわかります。
プロセスはCtrl + cで終了することができます。
開発スピードアップ
index.php
を少々いじります。
<?php // require_once 'fetchTester.php'; // $fetchtester = new FetchTester(); // $fetchtester->fetch("testtable"); // 引数:テーブル名 echo "Hello, Docker-compose!";
再度docker-compose up
してブラウザにアクセスすると、表示が変わるはずです。
前回の
DockerfileでPHP7環境構築
の記事を踏まえて読んでくださっている方はわかると思いますが、すごく楽です。前回はブラウザに
表示させるだけ、ポートフォワーディングするだけ、で長いコマンドを打たなくてはいけなかったのが、
docker-compose.yml
へすべて書いてしまうことで解決しています。
このファイルを開発メンバで共有すれば、コマンドを幾つか打つだけで同じ開発環境が整うのも得点高いです。
改良の余地アリ
まずMySQLのコンテナのIPアドレスを調べて設定しなければいけないプロセスが面倒ですね。
IPアドレスを固定でセッティングするようなこともできるような気もするので上手くいけば手順を省略
できます。
また、今回はphpMyAdminを使ってみたかったので試行できませんでしたが、MySQLの公式イメージでは
特定の(既存の)ディレクトリにSQLファイルを流し込むことで、データベース定義やテーブル作成、データの挿入
を自動で行ってくれるそうです。