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

  • 20
    Like
  • 0
    Comment

対象

まったくの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には戻らない気がする。