2016/09/06 アップデートしました

はじめに

Macとかで開発していると、Rubyのバージョンが揃えにくかったり、gem依存が…とか発生したりしますよね? かと言って、vagrantは重いし、、確かにboxを作れば共有はできるけど、、思いし

よし!それならDockerやん?と思っても、最近まで Docker For Mac じゃなくて、docker-machine でvb依存してるし…なぁ だったんですが、For mac の登場で、不便さがなくなったので、このタイミングでみんなDockerでやろうよ!
と言いたくて、色々継続開発しやすい?環境を模索してみました。

そして

よくネットに書かれている、Rails+Dockerの方法だと
Gemfile を更新するたびに、docker-compose build (イメージビルド)し直して、
docker-compose up コンテナ立ち上げみたいになってしまい、
実開発には少し不便だなーと思って、今回運用しやすいのではないか?環境を作りまとめました。

今回作成した物
https://github.com/shinofara/rails_docker_compose

動くけど運用には不向きだった物 https://github.com/shinofara/rails_docker_compose/tree/ee54ac6d786854b80524fcc6f958fb542268ea98

まずは使い方

README.md に書いてあるけど

作業環境をクローン

$ git clone https://github.com/shinofara/rails_docker_compose.git /path/to/workspace
$ cd /path/to/workspace

クローンした作業環境にRailsを配置

$ git clone https://github.com/shinofara/sample-rail5.git ./src

実行環境イメージ(Docker)の作成と実行

$ make && make up

実行が完了したらブラウザで開いてみよう

http://localhost/

何をしているかの説明はここから

この環境は、複数のDockerコンテナによってできています。

どんなDockerコンテナが存在するの?

コンテナ名 コンテナ用途
rails_nginx NginxによるHTTP環境
rails_app 現在はpuma専用Rails実行環境
rails_db Mariadbサーバ
rails_smtp schickling/mailcatcher というSMTP検証環境
過去にRailsプロジェクトでSMTPサーバ持ってないけど、メール送信機能が正常に動作してるか確認したいとき! を書きました
rails_phpmyadmin phpmyadmin環境、コマンドベースでDB見るのがめんどくさい時用

そして、実行コンテナとは別に、データボリューム用コンテナも存在します

コンテナ名 コンテナ用途
bundle-data rails_appコンテナ内で利用している、Bundleでgemをインストールする時用
mysql-data mysqlのdataディレクトリ

メインとなるDockerイメージの説明

rails_app用Dockerfile

FROM ruby:2.3-alpine
RUN apk update && apk upgrade

RUN apk add --update build-base mysql-dev nodejs tzdata && \
    rm -rf /var/cache/apk/*

イメージはDocker Hub で公開されている、alpineベースのrubyイメージを利用 そして、必要なパッケージをインストールして、イメージサイズを最小限にする為に、不要なキャッシュなどは削除しています。

ENV app /work/app
WORKDIR $app

作業ディレクトリ設定

# bundle install pathをdata containarに変更
ENV BUNDLE_PATH /bundle

ARG app_dir
COPY $app_dir $app

BUNDLE_PATH でbundle install先を bundle-data に変更 そして、アプリケーションディレクトリをイメージ内に COPY しています。 この時点では、bundle install は行っておりません。

肝心のdocker-compose.ymlの説明

docker-compose.yml

良があるので、rails_appに関係する箇所のみ書き出します

rails_app:
  build:
    context: .
    dockerfile: docker/app/Dockerfile
    args:
    app_dir: src

args で、ビルド時にDockerfile内の ARG に外部から値をセットします。

ARG app_dir

ここでは、src をDockerfile側にセットしています。 これで

ENV app /work/app
.
(中略)
.
ARG app_dir
COPY $app_dir $app

src$app を展開した /work/app にコピーしたことになります。 これで出来上がるイメージには、srcが格納された状態になりました。

volumes:
  - ${PWD}/docker/app/bin:/work/bin:ro
  - ${PWD}/src:/work/app
  - bundle-data:/bundle

volumes では、コンテナ実行時にコンテナ内部にマウントしたいディレクトリを書いてます。

- bundle-data:/bundle

これがdata volume containerになります。これでrails_app を何回作りなおしても、最初からbundle installをしなくても良いようになります。 いやーべんり

あと残りは、 command, depends_onlink ですが、

command: sh /work/bin/run.sh

だけ説明を書いておきます。 command はコンテナ実行時に内部で実行して欲しいコマンド
このシェルスクリプトが何をしているかというと

bundle check || bundle install
bundle exec puma -C config/puma.rb

こんな感じで、実行時に bundle-data 内にインストールしているパッケージをチェックして、 Gemfile に書かれているものとさいが無いか確認
差異があれば bundle install なければ、そのまま puma を実行するようになってます。

最後に

おい、つかいにくいわ!
なんやこれ、立ち上がらんやんけ
それよりこうしたらええんちゃう?

などありましたら優しく投げかけてください