この記事は12/1のDocker2 Advent Calendar, 12/3のHamee Advent Calendarの記事です。
こんにちは。
docker composeめちゃくちゃ便利ですよね。
Chef, Vagrant, Puppet, Ansible, Fabric…とプロビジョニングツールとか仮想化ツールを色々触ってきましたが、
それらよりずば抜けて扱いやすいと思っているツールです。
で、ローカルで開発している時に困るのが、 MySQLをはじめDBにデータを持ってもコンテナを破棄するとデータがすっ飛ぶ 問題です。
軽量なアプリの場合ならDB破棄してシード流して、、、という構成でもイケるかも知れませんが、多くの場合オーバーヘッドが大きすぎてまともに開発できなくなると思います。
Docker for Macを使用している場合はこの問題は難なく解消できるのですが、
docker-machineを使用している場合に恐らくドハマリするので、備忘録として残しておきます。
冒頭にも書きましたが、docker-compose + docker-machineでの話です。
ただ、互換性のためにDocker for Macでも動作確認はしております。
version: '2'
services:
db:
image: mysql:5.6
volumes:
- ./db/mysql_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=app
大枠このような感じになると思います。
volumesでローカルのディレクトリとMySQLコンテナのデータ領域をマウントしています。
これで、何かデータが書き込まれればローカルのファイルとして残るので、コンテナが消えてもデータが永続化されそうです。
何度でも書きますが、Docker for Macならこの書き方で問題になりません。意図したとおり動きます。 ですが、docker-machine環境においては、以下の問題が発生します。
docker-machineでvolumesを利用すると、
という感じです。
かなりのゴリ押しで、自分でも汚いと思っているハックですが、こんな解消方法で突破できました。
version: '2'
services:
db:
image: mysql:5.6
command: bash -c 'usermod -o -u 1000 mysql; groupmod -o -g 500 mysql; chown -R mysql:root /var/run/mysqld/; /entrypoint.sh mysqld --user=mysql --console'
volumes:
- ./db/mysql_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=app
command: ...
の行を足しました。
コンテナ起動時にデータ領域のパーミッション・オーナー・グループを書き換えてからmysqldを起動しています。
command
セクションに指定できる値はシェルではなく、
実行可能ファイルが1つめ、それ以降は全て引数という形式にエスケープされてしまいます。
単純に複数コマンドを書くことができません。なのでbash -c ...
と書いて複数行のシェルを実行しています。
Docker for Macでも動作確認しましたが、この構成で動いてくれました。
docker-compose使うならDocker for Mac使いましょう。色々つらくない。圧倒的に楽
もしチーム内に1人でもdocker-machineの人が居たら、上記のハックを使ったら良いと思います。
ベンチマーク取ってないので分かりませんが、
Docker for Macの方が主にマウント・ファイルI/O周りの速度が向上しているように感じます。
まだdocker-machineとDocker for Macの違いを体系的に理解できていないので、また別途記事を書きます。
上記の対応だけでは、エンコーディングの問題が解消していないので、マルチバイト周りでハマります。
こちらの記事も併せてご参照ください。