開発環境向けミドルウェア複数バージョン管理としてのDocker


対象

複数の案件を掛け持ちしつつ、開発環境はローカルのMacなどで開発し、複数バージョンのミドルウェアを混在させたい方には有用かもしれません。
僕の場合は複数のRailsアプリケーションを扱っていますが、DBのMySQLのバージョンが微妙に5.5のものから5.6のものなど複数あり、とりあえずローカルは5.6をいれて共有して使っていましたが、最新の5.7が使えないことや本番とバージョンが異なっていることを解消したくDockerで複数バージョン管理することにしました。

事前準備

ツールのインストール

  • Vartualbox
    適当に最新版入れてください。(試した環境は 5.1.2 r108956)

  • dockerdocker-machine
    Docker Toolbox をインストールするか、 homebrewなどで個別に dockerdocker-machine をインストールしてもいいです。

docker-machineでホスト用のマシンを起動

docker-machineはdockerのコンテナを起動させるためのVirtualboxのホストを操作するツールとなります。(--driver で他のドライバを指定することでVirtualboxではなくvmwareなども利用可能です。 サポートドライバ

devという名前のdockerホストを作成
$ docker-machine create --driver virtualbox dev
dockerホストの作成確認
$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
dev       *        virtualbox   Running   tcp://192.168.99.100:2376           v1.11.2

これにより、Virtualboxに dev という名前でインスタンスができます。

docker-machineを経由してdockerを利用

env を設定して docker コマンドを利用できるようになります。

以下のコマンドを打つことで、開いているターミナルのシェル上で、 docker コマンドを打つと docker-machine で動作しているDockerホストで操作している状態となります。

環境設定
$ eval $(docker-machine env dev)
以下の様なdockerコマンドをMac上で打つとDockerホスト上で実行される
$ docker ps
$ docker images

dockerで ミドルウェアごとの公式イメージを run してコンテナを起動します

MySQL, Redis, Postgres を複数バージョン管理するための記述を以下に記載していきます。

MySQLコンテナを管理

https://hub.docker.com/_/mysql/

以下の各 docker run コマンドのオプションを見てもらうとわかるように、明示的に起動するときにマッピングするポートをを変えることで複数のバージョンにアクセスできるようにしています。

MySQL5.6

以下のコマンドでMySQL5.6のコンテナを mysql56 という名前で立ち上げられます。
ポートを 3356 に マッピングし ボリューム を /var/lib/docker/mysql56 にマッピングします。

mysql5.6のイメージを取得してコンテナ起動する
docker run --name mysql56 -v /var/lib/docker/mysql56:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password -p 3356:3306 -d mysql:5.6 --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
接続方法
mysql -uroot -h$(docker-machine ip dev) -p -P3356

パスワードに password と入力します。

MySQL5.7

以下のコマンドでMySQL5.7のコンテナを mysql57 という名前で立ち上げます。
ポートを 3357 に マッピングし ボリューム を /var/lib/docker/mysql57 にマッピングします。

mysql5.7のイメージを取得してコンテナを起動する
docker run --name mysql57 -v /var/lib/docker/mysql57:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password -p 3357:3306 -d mysql:5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
接続方法
mysql -uroot -h$(docker-machine ip dev) -p -P3357

パスワードに password と入力します。

dockerコマンドの使い方

  • 個別にコンテナを止めたいときは、以下を実行します。
    $ docker stop mysql56

  • 個別でコンテナを起動させたい時は、以下を実行します。
    $ docker start mysql56

コンテナは作成済みで、コンテナだけを個別に起動したり、停止するときによく使います。(主に2回目以降ですでに docker rundocker create でコンテナを作成したあとに使います。

Redisコンテナを管理

https://hub.docker.com/_/redis/

redis3.0

ポートを 6330 に マッピングし ボリューム を /var/lib/docker/redis30 にマッピングします。

redis3.0のイメージを取得してコンテナを起動する
docker run --name redis30 -v /var/lib/docker/redis30:/data -p 6330:6379 -d redis:3.0
接続方法
redis-cli -h $(docker-machine ip dev) -p 6330

redis3.2

ポートを 6332 に マッピングし ボリューム を /var/lib/docker/redis32 にマッピングします。

redis3.0のイメージを取得してコンテナを起動する
docker run --name redis32 -v /var/lib/docker/redis32:/data -p 6332:6379 -d redis:3.2
接続方法
redis-cli -h $(docker-machine ip dev) -p 6332

Postgresコンテナを管理

https://hub.docker.com/_/postgres/

postgres9.4

ポートを 5494 に マッピングし ボリューム を /var/lib/docker/postgres94 にマッピングします。

postgres9.4のイメージを取得してコンテナを起動する
docker run --name postgres94 -e POSTGRES_PASSWORD=password -v /var/lib/docker/postgres94:/var/lib/postgresql/data -p 5494:5432 -d postgres:9.4

パスワードに password と入力します。
接続方法
psql -U postgres -h $(docker-machine ip dev) -p 5494

postgres9.5

ポートを 5495 に マッピングし ボリューム を /var/lib/docker/postgres95 にマッピングします。

postgres9.5のイメージを取得してコンテナを起動する
docker run --name postgres95 -e POSTGRES_PASSWORD=password -v /var/lib/docker/postgres95:/var/lib/postgresql/data -p 5495:5432 -d postgres:9.5
接続方法
psql -U postgres -h $(docker-machine ip dev) -p 5495

パスワードに password と入力します。

補足

補足1) 上記のように設定したdocker上で Railsを使った場合の database.yml の指定方法

config/database.yml(mysql5.6のDBを利用する場合)
development:
  adapter:   mysql2
  encoding:  utf8
  charset:   utf8
  collation: utf8_general_ci
  pool:      5
  username:  root
  password:  password
  host:      <%= `docker-machine ip dev` %>
  port:      3356
  database:  db_development

補足2) VOLUME の共有に /var/lib/docker/ を使っている理由

各環境の設定において docker run するときに必ず  -v /var/lib/docker/xxxxx:path/to/dir のような設定があったと思いますが、データを永続化するために指定しています。

docker-machineのOS(Dockerホスト)は / のマウントポイントは tempfs でフォーマットされているため、 docker-machine を停止してしまうと、基本的にはデータが消えてしまいます。
それを防ぐため、 /var/lib/docker/var/lib/boot2docker 以下にデータディレクトリを共有しておけば永続化されるので指定しています。
詳しくは以下も合わせてご参照ください。