LoginSignup
147
147

More than 5 years have passed since last update.

Vagrant+Dockerでローカルとコンテナ内が同期する開発環境の構築

Last updated at Posted at 2014-09-16

※2014/10/19追記
figを使ってもっとお手軽に同じようなことをする構成を別記事にしました!
http://qiita.com/toritori0318/items/190fd2dad2bf3ce38b88



Mac上でVagrantを起動し、その中にDockerコンテナを立ちあげ、
コンテナ内のソースとローカルのソースを同期させる開発環境を構築してみます。

そもそも何が目的なのか?

開発環境の配布です。
今までは setup.sh のようなもので
プログラム言語/関連モジュール/ミドルウェアなどをローカルにインストールして
開発環境を整えていましたが
共有ライブラリのバージョン違い/元環境とのコンフリクト/エンジニアのスキルセットなどにより
上手くいかないことも多々ありました。

そこで、すべての環境はVagrant(Docker)に置いて環境依存を無くし、
かつローカルのソースコードと同期することによって
あたかも全ての環境がローカルに存在するかのごとく振る舞うことが可能なVagrant環境を構築してみました。
つまり Vagrantだけあればすぐに開発できる環境が入手できる ということになります。

また、Vagrant直でやらないのは全部入りの環境を提供して作業させようとすると
VM起動が遅くそれがストレスになるからです。
アプリケーションだけでなくミドルウェアも含めてコンテナ化することで
軽量かつ汎用的な環境を配布できると考えました。

サンプルソースコード

こちらに置いてあります。
Vagrantは1.6以上が必要です。
https://github.com/toritori0318/flask-vagrant-docker-sample


サンプルの概要/ポートマッピング図

3つのコンテナを用意しています。

  • nginx
  • python-app
  • redis

python-app
アクセスする毎にカウントをインクリメントして表示
するだけの簡単なアプリです。Redisに情報を保存しています。

スクリーンショット 2014-09-15 3.08.52.png

nginxはpython-appの5000番ポートにリバースプロキシしており、
python-appはredisの6379番ポートにアクセスしています。

各コンテナはそれぞれ
nginx(10080)/python-app(15000)/redis(16379)
ポートフォワードさせ、ローカルMacから直接アクセスできるように設定しています。


ディレクトリ同期概要図

スクリーンショット 2014-09-15 3.09.06.png

Mac⇔Vagrant間はsynced_folder(NFS)で、
Vagrant⇔Dockerコンテナ間はvolume(正確にはdocker providerのvolumes)
実現しています。

Mac上の./logディレクトリは nginxコンテナのログ全般と、appサーバのデバッグログが同期されます。
./appディレクトリはpython-appコンテナのアプリケーションディレクトリと同期させています。

コンテナ間の通信について

linkを使います。
python-app ⇔ redis間はこのリンクを、
nginx ⇔ python-app間はこのリンクを 設定しています。
python-app内でredisを参照しているのはここで環境変数を読み込んでいるだけです。
nginxでは、直接nginx.confで環境変数を読み込むのが上手くいかなかったので1
run.sh内でsed置換しています。

開発フロー

ローカルMac上のappディレクトリ以下のファイルを修正します。
すると、python-appコンテナ上のappにも修正が反映し
自動で適用されます(自動適用はflaskの機能)。
また、ログファイルはローカルMac上の ./logディレクトリにリアルタイムで反映されるのでデバッグも容易です。


やってみよう

  1. まずは Dockerコンテナを起動します。

    vagrant up --provider=docker redis python-app nginx

  2. うまく動いているか確認してみます。

    curl http://localhost:10080/

    スクリーンショット 2014-09-15 4.32.36.png

  3. ./app/server.pyを修正してみます。

    スクリーンショット 2014-09-15 4.36.14.png

  4. しばらくすると自動で修正が反映された!

    スクリーンショット 2014-09-15 4.36.24.png

ローカルファイルだけでなく、
Dockerコンテナ内のファイルが修正されているのがポイントですね。


その他Tips

Dockerホストにログインするには?

vagrant sshでログインしたいところですが、
このVagrantfileで起動するとカレントホストには表示されません2
ですが、vagrant global-statusでidを探してログインすることは可能です。

vagrant ssh <id>

しかし、いちいちid指定するの面倒なので ssh-config に登録してしまいましょう。
これならvmを作りなおしたとしてもsshコマンドでそのままログインできます。

vagrant ssh-config <id>
(ホスト名が「default」になっているのでわかりやすいものに変えたほうが良いでしょう)

コンテナにログインしたい場合は?

サンプルでホストイメージとして使っている yungsang/boot2docker は
nsenter入りなので、それを使うと良いでしょう。
さらに docker-enterという便利コマンドもついているので
お手軽にログイン可能です

# docker-host上からログイン
docker-enter <コンテナID>

# Macから直接最新コンテナにログイン
ssh <ssh-configで設定したホスト名> 'docker-enter $(docker ps -l -q)'

ローカルPCからDockerコマンド実行したいんだけど

dockerコマンドインストール後にDOCKER_HOSTを指定すればOKです。

export DOCKER_HOST=tcp://localhost:2375

というかdockerコマンドはあったほうが便利なので
brewでインストールしておきましょう。

再度Docker Buildしたい場合は?

vagrant reload すると、Docker buildを再実行します。


問題点

Macの電源を落として再度Mac起動した後でDockerコンテナ起動しようとすると
volumeの適用がうまく行かずにエラーが出てしまいます。

スクリーンショット 2014-09-17 2.28.16.png

これは、一度コンテナを削除して再度作りなおすとうまくいくのですが
このオペレーションを開発者に強制するのも酷ですし、
ここはどうにかして回避したいと考えています。
もしかしたらDocker-providerを使わずにfigなどで自前起動すれば問題ないのかな〜と思っているので
今後検証してみる予定です。


まとめ

コンテナ上のファイルと同期して、
ローカルPCに直接環境構築することなく開発できる環境を作ってみました。
この構成、まだいくつか問題があって絶賛検証中なので
もっと良い方法があればご教授頂ければと思います!




1. うまいやり方があれば知りたい
2. もしかして表示する方法あるんでしょうか?

147
147
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
147
147