巷で噂の Docker
弊社でも主に開発環境の用途で使っていますよ!

そこで今回は、Webサービス開発の場面を想定した構成で Docker したいと思います!

目標

nginx + PHP-FPM (+ Phalcon) + MySQLRedis の環境を、Docker 使ってローカルに立ち上げて、ちょっと開発する

手順

1. Docker Toolbox のインストール

Docker Toolbox は、Docker 周りのツールいろいろをいっぺんに使えるようにしてくれる素敵なやつです!(ちょっとドキュメントが少なくて困ったけど…)

[bash]brew cask install dockertoolbox[/bash]

Mac だとこれだけですね!これで virtualbox と dockertoolbox のパッケージがインストールされます。
Windows 用も用意されてるようですのでチェックしてみてください!

Docker Toolbox で手に入るツールをまとめるとこんな感じです。

  • Docker CLI クライアント
    docker コマンドですね。
    イメージやコンテナを作る Docker Engine を操作できます。
  • Docker Machine
    docker-machine コマンドですね。
    Docker Engine のホストを作成・操作できるので、Mac 上のターミナルから Docker Engine のコマンドが使えるようになったり、AWSなどのリモートシステムにホストをデプロイできるようにもなります。
  • Docker Compose
    docker-compose コマンドですね。
    複数コンテナの定義と実行ができるようになります。
  • Kitematic
    Docker のGUIツールです。
  • Docker QuickStart Terminal
    さっき起動したやつですね。
    Docker のコマンドライン環境向けにあらかじめ設定されているシェルです。
  • Oracle VM VirtualBox

チュートリアルにあるように、ちゃんとインストールされたか確認してみましょう!

Docker Quickstart Terminal.app を起動して、どのターミナルで立ち上げるか選択すると…
Docker Quickstart Terminal.app を起動

処理走ってクジラが!

なんか処理走ってクジラが出ます!

さらに

[bash]docker run hello-world[/bash]

を叩いて、全部いい感じに処理されるかチェックするとのこと。

それー。
docker run hello-world

いけましたね。問題なさそう!
ちなみに docker run は、Dockerコンテナを作成・起動するコマンドになります。

メッセージを読むと、
Docker クライアントが Docker デーモンに接続できて、
Docker デーモンが Docker Hub から “hello, world”イメージを pull してこれて、
Docker デーモンがイメージからコンテナを作成できて、
Docker デーモンが Docker クライアントに出力を渡せたので、
このメッセージが見れてる、ということのようです。ふむ…。

いろいろ調べて整理した結果、
こう理解しました(ツッコミあれば2秒で修正します!

Docker Engine のデーモンは Linux上でしか動かない

Docker Machine コマンド(と VirtualBox)使って、Mac上で Linux の VM が作成される

Linux VM が Docker Engine をホストする

Docker QuickStart シェル + Docker CLI で、(Mac上で動く)VM 上で動く Docker Engine を(特に設定なしで)操作することができる!

むずい!

2. docker compose 使って、各サービスを使えるようにする

さて、Docker 環境が手に入りました。
続いて、各サービスのコンテナを立ち上げましょう!

今回は nginx + PHP-FPM(+ Phalcon)+ MySQLRedis な環境を作りたいのですが、それぞれのイメージを協調させて動かしたい時に、docker-compose が便利!ということのようです。

※ Docker Hubでイメージを調達
参考: Docker Hub 入門
※ 自分でイメージを作成
参考: Docker イメージの作成

ちなみに今回のイメージはすべて、Docker Hub にあがってたものを適当に選んで使ってみてる感じです!
※ Docker Hub のアカウントを作っておきましょう。

1. まずは作業用ディレクトリを作成

[bash]mkdir docker_test[/bash]

適当に作ります。今後はこのディレクトリの中にアプリケーションのコードを置いたり、定義ファイルを置いたりしていくことになります。

2. phalcon-devtools でプロジェクト作成

[bash]phalcon create-project sample[/bash]

サクッとプロジェクトを作ります(普段の業務ではあんまり使ってないですが…)。
コマンド叩くとディレクトリ構造がこうなります!

d6

3. docker-compose.yml を定義

アプリケーションがどういうサービスを使って動くのか、YAML形式で定義します。

設定ファイルはこんな感じになります。サービスごとに必要な設定を記述する感じです。

4. docker-compose up でアプリケーションを立ち上げる

では立ち上げてみます!

[bash]docker-compose up[/bash]

docker-compose up

ブオーっと流れて

docker-compose upの続き

止まりました。起動し終わったんでしょうか?確認したいけど、URLがわからず…。
調べてみると、Mac では VM の IPとポートを指定すればいいみたいなので、一度 Ctrl-c で停止して、docker-machine コマンドで確認してみます。

[bash]docker-machine ip default[/bash]

default はその名の通り、デフォルトの VM 名になります。

docker-machine ip default
確認できました。

では今度は detach モードというバックグラウンド実行モードで立ち上げて、ブラウザから確認してみましょう!

[bash]docker-compose up -d[/bash]

docker-compose up -d
すると…。

Congratulations!

Thank you! ひとまず Phalcon が動いてることを確認できました。
続いて MySQL と Redis が起動・接続できていることを、ローカルから確認してみます!

Phalcon が動いてることを確認

ユーザ はroot 、パスワードは MYSQL_ROOT_PASSWORD で指定したものを入力しています。問題なく接続できてますね!(yml で別途設定している通り、sample / hoge でも接続できます)

Redis の方も接続できました!

また、Redis の方も接続できました!

4. MySQL と Redis と連携させつつちょっと開発してみる

ではせっかくなんでちょっと開発してみます!
今回は、MySQL にアクセスログを保存・表示しつつ、Redis でページアクセスをカウントして表示という、うんこアプリケーションを作ってみます!

1. DBコンテナ起動時のデータ投入

まずは、MySQL のテーブルを作りたいですね。
公式の MySQL イメージでは、コンテナ起動時にデータを投入できる仕組みが用意されているようで、コンテナの /docker-entrypoint-initdb.d 配下に .sh や .sql を配置しておくとそれらを実行してくれるという感じっぽいです。

こちらの記事が参考になりました!
DockerのOfficial imageのMySQLを使って初回起動時にカスタムSQLを実行させる

なので SQL ファイルを配置したローカルの任意のディレクトリを、コンテナ側の /docker-entrypoint-initdb.d としてマウントさせることにします。

コンテナの起動時に任意のデータを投入

こんな感じ。これで db コンテナの起動時に任意のデータが投入できます。

2. phalcon-devtools でモデルのソースコードを生成

再度 docker-compose up -d で db コンテナを再起動するとテーブルが作成されているので(※1)、app/config.php の DB 接続設定を修正しつつ、phalcon-devtools でモデルを生成しちゃいます。
この時、DB のホスト設定は、サービス名の “db” でOKです(ポートを変えていたら例えば “db:3307″とかに)。
参考: Networking in Compose

[sourcecode lang=”bash”]phalcon model –name access_log –get-set[/sourcecode]

※1 テーブルが作成されないこともあったり…。最終的には問題なくいったのですが、その条件がちょっと不明です…。

3. IndexController 実装して DB と連携してみる

リクエストごとにサーバ変数から値を取得して、DB に保存。過去のアクセス情報をリスト表示しているだけです。あと view もちょっといじって…

IndexController 実装して DB と連携
保存と取得ができているようです!(まあ、うんこですがね
そして次節、 Redis の連携で最後です!

4. Redis の php 拡張が入っていないことに気づき、Dockerfile で独自イメージを作ってみる

盲点でしたね。alfonso/nginx-phalcon には phpredis 入ってませんでした!
なので nginx-phalcon を元に、phpredis だけ追加したイメージを作って、それを使うことにします!

おもむろに、以下のような Dockerfile を作成します。

こんなノリで Dockerfile を書いてビルドするとイメージが作れちゃうんですね。

次に、docker-compose.yml の web の部分を編集して、nginx-phalcon イメージを使わず、この Dockerfile を元にしたイメージを使うようにします。

これで OK です!
Phalcon 側の Redis の接続設定を整えて、アクセスカウント用に Redis の incr を呼んだらできあがりです!

 

Sampleアプリケーション
favicon のアクセス混ざっててよりうんこ感が増してますが、アクセスカウント取れてますね!

うまくいかない時は

今回端折っていますが、割とトライアンドエラーしました。
そういう時は以下のような形で確認してみるといいかもしれません。

  • docker logs コマンドで、コンテナ起動時のログを確認
    attach モード(-d オプションつけない)で起動しても確認できますが、コンテナを指定できるので便利です。
  • コンテナ内のログファイルを直接 tail -f、どころかコンテナにログインも

    [sourcecode lang=”bash”]docker exec -it <コンテナ名 or ID> tail -f /var/log/見たいログ  [/sourcecode]

    みたいな感じで、コンテナ内のファイルが参照できます。tail -fbash とかに置き換えると普通に中に入れます。

まとめ

ちょっと長くなっちゃいましたが、Docker 素敵。

あわせて読みたい記事