Rails
Docker
docker-compose

Docker Compose と Rails(+MySQL) で開発環境作成したときに気になったポイント

More than 1 year has passed since last update.


対象

まったくのdocker初心者がクイックスタート・ガイド:Docker Compose と Railsを一通りやっても、いまいち納得できなかった人。つまり私。


目的

ある程度モヤモヤをスッキリさせて開発環境の雛型みたいなものまで持っていきたい。


私の行った手順

クイックスタート・ガイド:Docker Compose と Railsを一読したことを前提に書いていきます。


dockerディレクトリの作成

クイックスタートを一通り実行するとアプリケーションルートにDockerfileやdocker-compose.ymlがあるのが気になります。docker-compose.ymlはここにあるのがベターに思えますが、今後Nginxを組み込んだり、MySqlの永続化を考えるとdocker関連は一か所に押し込めたくなります。

そんなわけで、以下のディレクトリ構成にしました。

全ファイルをGitHub上に置いておきます。

docker-rails/

|-docker-compose.yml #これはこの場にあったほうがいい
|-Gemfile
|-Gemfile.lock
|-docker/
|-mysql/
| |-password.yml #MySQLのパスワードはここに記述
| |-volumes/ #このフォルダにMySQLのデータを永続化
|-rails/
| |-Dockerfile #Rails用のDockerfile


プロジェクトの定義


Dockerfileの作成

apt-getをMySQL用に変更。Gemfileは/tmpに置く。


./docker/rails/Dockerfile

FROM ruby:2.3.3

ENV LANG C.UTF-8
# for MySQL
RUN apt-get update -qq && apt-get install -y build-essential mysql-client nodejs

RUN gem install bundler

WORKDIR /tmp
ADD Gemfile Gemfile
ADD Gemfile.lock Gemfile.lock
RUN bundle install

ENV APP_HOME /myapp
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
ADD . $APP_HOME



Gemfileを作成

変更点無し

証明書エラーで落ちる時はhttp://rubygems.orgから持ってくる。


./Gemfile

source 'http://rubygems.org'

gem 'rails', '5.0.1'


Gemfile.lock(空ファイル)を作成

変更点無し

$touch Gemfile.lock


docker-compose.ymlを作成

変更箇所は以下の通り。


  • dbのvolumesでデータベースを永続化

  • dbのextendsでパスワードをpassword.ymlで管理

  • webのextendsでパスワードをrailsにも教える。


  • extends先のファイルにパスワードを設定。

  • webのbuildでDockerfileの場所を指定。


docker-compose.yml

version: '2'

services:
db:
image: mysql:5.7.17
ports:
- "3306:3306"
volumes:
- ./docker/mysql/volumes:/var/lib/mysql
extends:
file: ./docker/mysql/password.yml
service: password
web:
build:
context: .
dockerfile: ./docker/rails/Dockerfile
command: bundle exec rails s -p 3000 -b '0.0.0.0'
ports:
- "3000:3000"
volumes:
- .:/myapp
environment:
RAILS_ENV: development
extends:
file: ./docker/mysql/password.yml
service: password
depends_on:
- db


./docker/mysql/password.yml

version: '2'

services:
password:
environment:
MYSQL_ROOT_PASSWORD: password

MYSQL_ROOT_PASSWORD: passwordpasswordの部分がMySQLのパスワードになる。


プロジェクトの作成

特に問題なくガイド通りに進められる。

databaseはMySQLなのでそこは変更する。

$ docker-compose run --rm web rails new . --force --database=mysql --skip-bundle

$ docker-compose build


データベースに接続


config/database.ymlを編集

passwordを環境変数から取得するように変更。

hostdbにする。


config/database.yml

default: &default

adapter: mysql2
encoding: utf8
pool: 5
username: root
password: <%= ENV['MYSQL_ROOT_PASSWORD'] %>
host: db

development:
<<: *default
database: myapp_development

test:
<<: *default
database: myapp_test



データベース作成

upが出来たのを確認したらそのまま落としても問題ないです。

$ docker-compose up

$ <ctrl-C>
$ docker-compose run --rm web rake db:create


アプリ作成

本当にDBと連携して動いているのか確認するために簡単にアプリを作ってみる。


みんな大好きscaffold

docker-compose up-dオプションが良いと思う

$ docker-compose down

$ docker-compose run --rm web rails g scaffold item name:string amount:integer memo:text
$ docker-compose run --rm web rake db:migrate
$ docker-compose up -d

これで http://localhost:3000/items にアクセスして弄れることを確認。

docker-compose down docker-compose upを繰り返しても問題ないことを確認。

docker-compose upしたままviewやcontrolerを弄ってもブラウザ上に反映されることを確認。


Nginxも含めた環境づくり

また今度、暇になったら記事にしてみたい。


もやもやポイントまとめ


docker-composeコマンド編


サービス起動したら裏に回ってくれ。

docker-compose up -dにする。


サービス終了はどうするの?

docker-compose downする。

docker-compose upで回していたらCtrl+Cで強制終了。


MySQL編


対話的に設定したい

イメージ単独では何故か出来ません。

いや、対話用のMySQLクライアント作れば行けるのだろうが、railsコマンドで十分でしょ。

rootユーザーで操作しているのが気になるけど、どうやって対話以外でユーザー作成するのかわからんし。

rails dbconsoleがあったか。

早速、キャプチャ.PNG

ん?rootがフルオープンだぞ?

ってことは開発機からもアクセスできるんじゃない?

キャプチャ2.PNG

出来た。

dockerのnetworkの外からアクセスさせたくない時は下のportsを消せばdocker内のrails以外からはアクセス出来なくなる。


docker-compose.yml

version: '2'

services:
db:
ports:
- "3306:3306"


dbのデータってどこにあるの?

mysqlのイメージ内で勝手にdockerディレクトリに永続化されているので、以下の設定を追加して開発ディレクトリ内に持ってくる。


docker-compose.yml

services:

db:
volumes:
- ./docker/mysql/volumes:/var/lib/mysql


dbのパスワードって?

以下のように書くとrootのパスワードを設定できる。


docker-compose.yml

services:

db:
environment:
MYSQL_ROOT_PASSWORD: passward

ただしdocker-compose.ymlにMySQLのパスワードを直接書きたくないのでextendsを使って、以下のようにパスワードファイルに追い出す。

ついでにrails環境にもパスワードを渡す。


docker-compose.yml

services:

db:
extends:
file: ./docker/mysql/password.yml
service: password
web:
extends:
file: ./docker/mysql/password.yml
service: password


./docker/mysql/password.yml

version: '2'

services:
password:
environment:
MYSQL_ROOT_PASSWORD: password

これでpassword.ymlを.gitignoreで除外すればオールクリア。


Rails編


web_consoleが使えない

railsアプリに以下を追加。


config/environments/development.rb

config.web_console.automount = true

config.web_console.whitelisted_ips = %w( 0.0.0.0/0 ::/0 )


最後に

今までVirtualBoxを使っていたけど、dockerは一度設定した後は手軽かも。

最初は設定・設定・また設定でうんざりしたけど、よく考えたらプロビジョニングとそんなに変わらんなぁと。

多分VirtualBoxには戻らない気がする。