mmts1007’s diary

プログラミング関連の技術系ブログです。

Docker で Rails の開発環境を構築する

Docker で Rails の開発環境を配れたら、楽できるのでは?思い、サンプルを作ったのでまとめる。

サンプルコード

github.com

Dockerfile と docker-compose.yml は以下の通り

Dockerfile.development

FROM ruby:2.4.1
MAINTAINER mmts1007

ENV APP_ROOT=/usr/src/app

WORKDIR $APP_ROOT
EXPOSE 3000

RUN apt-get update && apt-get install -y \
      nodejs \
      mysql-client

COPY . $APP_ROOT
RUN bundle install

CMD ["bundle", "exec", "rails", "s", "-b", "0.0.0.0"]

docker-compose.yml

version: '3'
services:
  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
    volumes:
      - mysql-data:/var/lib/mysql
  web:
    build:
      context: .
      dockerfile: Dockerfile.development
    volumes:
      - .:/usr/src/app
    ports:
      - "3000:3000"
    depends_on:
      - db
volumes:
  mysql-data:

工夫した点

  • 開発時は DB も必要になるため、 docker-compose を利用して 1コマンドで開発に必要がものが揃うようにした
  • 修正したソースコードをすぐに反映したかったため、ソースコードは Docker コンテナにマウント
  • DB に書き込んだデータは保持したかったので、 volumes を使って永続化

使い方

docker-compose build

$ pwd
/path/to/docker-rails/simple_note
$ docker-compose build
...
Successfully tagged simplenote_web:latest

docker-compose up

$ docker-compose up
Starting simplenote_db_1 ... 
Starting simplenote_db_1 ... done
Recreating simplenote_web_1 ... 
Recreating simplenote_web_1 ... done
Attaching to simplenote_db_1, simplenote_web_1
...
web_1  | Use Ctrl-C to stop

ブラウザから http://localhost:3000 にアクセス

その他

初回起動時は DB、テーブルが存在しないため作成する

$ docker-compose run web bundle exec rake db:create
$ docker-compose run web bundle exec rake db:migrate

追記

Gem ファイルの永続化

記事を公開したところ、先輩に「Gemfile 更新時に、全 Gem インストールし直しになっちゃうから Gem ファイルのインストール先も Volume にするのが良いよ」とコメントを頂きました。(ありがとうございます!)

確かに Gemfile 更新した時に毎回 build して、イメージに含めてあげないと動かない状態でした・・・

Gemfile に Kaminari を追加

gem 'kaminari'

bundle install

$ docker-compose run web bundle install
...
Fetching kaminari-core 1.0.1
Installing kaminari-core 1.0.1
...
Fetching kaminari-activerecord 1.0.1
Installing kaminari-activerecord 1.0.1
Fetching kaminari-actionview 1.0.1
Installing kaminari-actionview 1.0.1
...
Fetching kaminari 1.0.1
Installing kaminari 1.0.1
...
Bundle complete! 18 Gemfile dependencies, 76 gems now installed.
Bundled gems are installed into /usr/local/bundle.

もう一度 bundle install を実行すると キャッシュされて Gem は何もインストールされないことを期待していましたが・・・

$ docker-compose run web bundle install
...
Fetching kaminari-core 1.0.1
Installing kaminari-core 1.0.1
...
Fetching kaminari-activerecord 1.0.1
Installing kaminari-activerecord 1.0.1
Fetching kaminari-actionview 1.0.1
Installing kaminari-actionview 1.0.1
...
Fetching kaminari 1.0.1
Installing kaminari 1.0.1
...
Bundle complete! 18 Gemfile dependencies, 76 gems now installed.
Bundled gems are installed into /usr/local/bundle.

全く同じログが出ました・・・

新たに作成したコンテナに Gem をインストールし、そのコンテナは破棄されてしまうため、このような現象が起きてしまいました。

docker-compose.yml を以下のように変更し、インストールした Gem を永続化するようにしました。

iff --git a/simple_note/docker-compose.yml b/simple_note/docker-compose.yml
index 18e6132..c824f93 100644
--- a/simple_note/docker-compose.yml
+++ b/simple_note/docker-compose.yml
@@ -12,9 +12,11 @@ services:
       dockerfile: Dockerfile.development
     volumes:
       - .:/usr/src/app
+      - gem-store:/usr/local/bundle
     ports:
       - "3000:3000"
     depends_on:
       - db
 volumes:
   mysql-data:
+  gem-store:

この状態であればコンテナが破棄されたとしても Gem 自体は残るので、先ほどの問題は発生しなくなりました!

参考

docs.docker.com

qiita.com