読者です 読者をやめる 読者になる 読者になる

Docker Composeで開発環境を作る

AdventCalendar2015 mysql docker docker-compose

Docker Composeはいいぞ!

この記事はTech KAYAC Advent Calendar 2016の15日目の記事です。

こんにちは
この6月にKAYACに中途入社し技術部でゲームのサーバーサイドを担当しているひだかです。
新卒でも中途入社でも研修などを終え実務に入った時に一番最初に悲しい思いをするのは開発環境構築の作業ではないでしょうか?
実際に私もあまり整備されていないドキュメントを何度も見て、長い時間をかけやっと構築完了したと思ったらミドルウェアのバージョンが違うとかで序盤からやり直しということがありました。
知らない言語やOSやミドルウェアやフレームワークやモジュール群を前に新人はあまりにも無力です。

そんな時はInfrastructure as Codeです。Dockerを使うのです。
誰でもボタンポチーで開発環境を立てられるDockerを使うのです。
幸いなことにDocker for Mac/Windowsが今年7月に正式リリースされ、つい先日にもDocker for Aws/Azureが発表されローカルでもリモートでもDockerを触れる環境が充実しました。
確実に機運が高まっています。乗りましょうビッグウェーブに。


f:id:mamimumemoomoo:20161214222333p:plain
Uninstall寸前のDockerのクジラもかわいいですね

Docker Compose軽く説明

Dockerをとても簡単に説明すると、設定をコードとして書ける軽い仮想環境(コンテナ)です。
Docker Composeは名前の通り複数のコンテナをまとめて管理や操作ができるものです。

例えば簡単なアプリケーションの環境の開発環境を立てたい時にアプリケーション用コンテナ、DB用コンテナ、KVS用コンテナの3コンテナを用意する必要があり、 起動するだけでもDockerだけの場合はそれぞれのコンテナに対してdocker runしないといけません。
一方、Docker Composeの場合はdocker-compose upというコマンドだけで3コンテナを起動してくれます。
またDocker Composeは簡単な定義のみでコンテナ間の通信ができるようになります。

Docker Composeでしたこと

今回は普段MacのVagrant上で動かしていた開発環境をDocker Composeに置き換えました。
上記の開発環境構築がつらい問題に加え、本番DBはマスタスレーブ構成なのに開発環境では単一のDBのためレプリケーションとトランザクションまわりのCIや確認ができないといった問題もありました。

なので今回作ったDocker Composeは以下の4つのコンテナから構成しています。

  • アプリケーション用コンテナ
  • KVS用コンテナ
  • マスタDB用コンテナ
  • スレーブDB用コンテナ

実装

自由な社風の会社とはいえ、仕事用に作った定義ファイルを公開すると怒られるので上記の構成を最低限にまとめました。

github.com


レプリケーション部分は以下のブログを参考にさせていただきました。
ありがとうございます。

techblog.kayac.com

tkyshm.hatenablog.com

qiita.com

各ファイルに書いていることは基本的なことなので公式を見れば分かるかなという感じです。

Compose ファイル・リファレンス — Docker-docs-ja 1.12.RC ドキュメント

動かしてみる

前準備

Docker for MacやDocker for Windowsをインストールしてdockerコマンドが使えるようにしておいてください。

$ docker -v
Docker version 1.12.3, build 6b644ec

Docker Composeを立ち上げる

// とりあえずclone
$ git clone https://github.com/mamimumemoomoo/docker-compose-base.git
$ cd docker-compose-base/

// コンテナを立ち上げるためのイメージを作る
$ docker-compose build

// コンテナを立ち上げる 標準出力で立ち上げ時のログが流れてるのが分かる
$ docker-compose up

// 正常に立ち上がったらこんな感じ
// docker-compose upの1コマンドで4つのコンテナが立ち上がったのが分かる
$ docker-compose ps
          Name                         Command               State          Ports
-----------------------------------------------------------------------------------------
dockercomposebase_app_1     /bin/bash                        Up      0.0.0.0:8080->80/tcp
dockercomposebase_db_r_1    docker-entrypoint.sh mysqld      Up      3306/tcp
dockercomposebase_db_w_1    docker-entrypoint.sh mysqld      Up      3306/tcp
dockercomposebase_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp

// コンテナにアクセスするのにCONTAINER IDが必要なのでdocker psコマンド実行
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
6949824352e1        app                 "/bin/bash"              3 minutes ago       Up 3 minutes        0.0.0.0:8080->80/tcp   dockercomposebase_app_1
2377ec307496        mysql:slave         "docker-entrypoint.sh"   3 minutes ago       Up 3 minutes        3306/tcp               dockercomposebase_db_r_1
7ba45c25402e        mysql:master        "docker-entrypoint.sh"   3 minutes ago       Up 3 minutes        3306/tcp               dockercomposebase_db_w_1
09022930aca0        redis:3.0           "docker-entrypoint.sh"   3 minutes ago       Up 3 minutes        6379/tcp               dockercomposebase_redis_1

コンテナにアクセスと機能のチェック

// appのコンテナにアクセス ハッシュはpsのCONTAINER IDに応じて
$ docker exec -it 6949824352e1 bash
[root@6949824352e1 /]# 

// コンテナ内でDBを見てみる
// -h db_wでマスタ用DBアクセス、-h db_rでスレーブ用DBアクセスできる
[root@6949824352e1 /]# mysql -u root -h db_w -proot -e "show databases;"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
[root@6949824352e1 /]# mysql -u root -h db_r -proot -e "show databases;"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

// db_wのみにcreate databaseして、db_rにレプリカされてるのを確認
[root@6949824352e1 /]# mysql -u root -h db_w -proot -e "create database docker_compose_saikou;"
[root@6949824352e1 /]# mysql -u root -h db_w -proot -e "show databases;"
+-----------------------+
| Database              |
+-----------------------+
| docker_compose_saikou |
| information_schema    |
| mysql                 |
| performance_schema    |
| sys                   |
+-----------------------+
[root@6949824352e1 /]# mysql -u root -h db_r -proot -e "show databases;"
+-----------------------+
| Database              |
+-----------------------+
| docker_compose_saikou |
| information_schema    |
| mysql                 |
| performance_schema    |
| sys                   |
+-----------------------+

// redisにも接続できることを確認
// -h redisでredis用コンテナに接続
[root@6949824352e1 /]# redis-cli -h redis
redis:6379> set "docker-compose"
(error) ERR wrong number of arguments for 'set' command
redis:6379> set key "docker-compose"
OK
redis:6379> get key
"docker-compose"

// http確認 まだhttpサーバ動かしてないのでFailed connect
[root@6949824352e1 /]# curl localhost
curl: (7) Failed connect to localhost:80; Connection refused
// nginx起動
[root@6949824352e1 /]# nginx
// http確認
[root@6949824352e1 /]# curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
... HTML省略 ...

// MacやWindowsなどのホスト側で見られるか確認
// コンテナの80番ポートをホスト側の8080番ポートに転送してる
$ curl localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
... HTML省略 ...

// 起動中のコンテナを落とす
$ docker-compose down

はい、以上で最小構成の動かし方と機能の確認でした。

今後の展望

  • まだまだ使用実績がないので使い倒す
  • 安定したらとりあえずチーム内で布教する
  • CI用サーバもDocker Composeにする(マスタスレーブ構成にしたい)
  • 社内で確認や検証をする際にmirageを使っていて、ここのDockerをDocker Compooseにする(マスタスレーブ構成にしたい)

明日のTech KAYAC Advent Calendar 2016

明日のTech KAYAC Advent Calendar 2016もりごさんです!

「んー、ヒャー 驚きました ヒャー こんなことがあるんですねっていう大逆転ですね ヒャー」という意気込みらしいのでとても楽しみです!

f:id:mamimumemoomoo:20161215102842p:plain