DockerでRails5.1&React.js＆es6な環境を構築する

もうrbenvとかから開放されたい。全てdocker上で環境構築してチーム内での環境差異をなくしたい。
さらに言えば、jQueryからも開放されたい。なのでRails5.1から追加されたwebpackerをサクッと使ってjQuery依存無し、React.js&es6なアプリケーションの土台を作る。

# **ベースアプリケーションを作る**
まず`Dockerfile`を作り、

``` :Dockerfile
FROM ruby:2.4.1
LABEL maintainer 'kazuya Hara <kazuya@example.com>'

# set environment variables
ENV LANG C.UTF-8
ENV ROOT_PATH /appname

# install essential libraries
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev

# install node.js
RUN curl -sL https://deb.nodesource.com/setup_7.x | bash - && \
    apt-get install nodejs

# install yarn
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt-get update && apt-get install -y yarn

# move to root
RUN mkdir $ROOT_PATH
WORKDIR $ROOT_PATH

# bundle install
ADD Gemfile $ROOT_PATH/Gemfile
ADD Gemfile.lock $ROOT_PATH/Gemfile.lock
RUN bundle install

ADD . $ROOT_PATH
```

次に`Gemfile`でRailsのバージョンを指定し、


```ruby:Gemfile
source 'https://rubygems.org'
gem 'rails', '5.1.3'
```

空白の`Gemfile.lock`も作っておき、

``` 
$ touch Gemfile.lock
```

最後に`docker-compose.yml`でdbとserverを設定し、

```yaml:docker-compose.yml
version: '3'
services:
  db:
    image: postgres
  server:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/appname
    ports:
      - "3000:3000"
    depends_on:
      - db
```

`rails new`でアプリケーションを作る。オプションはお好みで。

```
$ docker-compose run server bundle exec rails new . --force --database=postgresql -T
```

# **webpackerでreactをセットアップする**

`Gemfile`にwebpackerを追加して、

```ruby:Gemfile
ruby '2.4.1'
source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

gem 'rails', '~> 5.1.3'

gem 'bcrypt', '~> 3.1.7'
gem 'jbuilder', '~> 2.5'
gem 'pg', '~> 0.18'
gem 'puma', '~> 3.7'
gem 'sass-rails', '~> 5.0'
gem 'therubyracer', platforms: :ruby
gem 'turbolinks', '~> 5'
gem 'uglifier', '>= 1.3.0'
gem 'webpacker', '~> 2.0'

group :development, :test do
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  gem 'listen', '>= 3.0.5', '< 3.2'
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  gem 'web-console', '>= 3.3.0'
end
```

ビルドします。

```
$ docker-compose build
```

あとは

```
$ docker-compose run server rails webpacker:install
$ docker-compose run server rails webpacker:install:react
```

でreactをrailsに乗せるためのセットアップが完了する。または

```
$ docker-compose exec server /bin/bash
```

でbashに入ってから

```
$ rails webpacker:install
$ rails webpacker:install:react
```

を実行しても良い。

# **serverとdbを繋げる**
ベースとなるrailsアプリケーションが作成されたら、`config/database.yml`を編集してrailsとdbが繋がるようにする。通常のrailsアプリだとhostは`localhost`をデフォルトとして想定しているが、今回はこれを`db`に変更している。

```yaml:config/database.yml
# PostgreSQL. Versions 9.1 and up are supported.
#
# Install the pg driver:
#   gem install pg
# On OS X with Homebrew:
#   gem install pg -- --with-pg-config=/usr/local/bin/pg_config
# On OS X with MacPorts:
#   gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
# On Windows:
#   gem install pg
#       Choose the win32 build.
#       Install PostgreSQL and put its /bin directory on your path.
#
# Configure Using Gemfile
# gem 'pg'
#
default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # http://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: appname_development

  # The specified database role being used to connect to postgres.
  # To create additional roles in postgres see `$ createuser --help`.
  # When left blank, postgres will use the default role. This is
  # the same name as the operating system user that initialized the database.
  username: postgres

  # The password associated with the postgres role (username).
  password:

  # Connect on a TCP socket. Omitted by default since the client uses a
  # domain socket that doesn't need configuration. Windows does not have
  # domain sockets, so uncomment these lines.
  host: db

  # The TCP port the server listens on. Defaults to 5432.
  # If your server runs on a different port number, change accordingly.
  #port: 5432

  # Schema search path. The server defaults to $user,public
  #schema_search_path: myapp,sharedapp,public

  # Minimum log levels, in increasing order:
  #   debug5, debug4, debug3, debug2, debug1,
  #   log, notice, warning, error, fatal, and panic
  # Defaults to warning.
  #min_messages: notice

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: appname_test

  # The specified database role being used to connect to postgres.
  # To create additional roles in postgres see `$ createuser --help`.
  # When left blank, postgres will use the default role. This is
  # the same name as the operating system user that initialized the database.
  username: postgres

  # The password associated with the postgres role (username).
  password:

  # Connect on a TCP socket. Omitted by default since the client uses a
  # domain socket that doesn't need configuration. Windows does not have
  # domain sockets, so uncomment these lines.
  host: db

# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
#   DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
#   production:
#     url: <%= ENV['DATABASE_URL'] %>
#
production:
  <<: *default
  database: appname_production
  username: appname
  password: <%= ENV['SPECTRA_DATABASE_PASSWORD'] %>
```

あとはdbを作成するだけ。

```
$ docker-compose run server rails db:create
```

# **立ち上げる**
railsは

```
$ docker-compose up
```
で立ち上がるし、

```
$ docker-compose run server bin/webpack-dev-server
```

でwebpack用のdev-serverを立ち上げておけば、JSを更新するたびにホットリロードしてくれる。