DockerでRailsを開発するためのファーストステップ


ある環境では動いていたのに、他の人の環境では動かなくなってしまったり、複数のプロジェクトに関わっていて、あるアプリケーションをアップグレードしたら、こっちのプロジェクトで動かなくなってしまう事が多々ありました。

gemとかであれば`bundler`がうまい具合に環境の差異を吸収してくれるのですが、ネイティブのライブラリを使い始めると、はまることが多くなってきます。
例えば、PostgreSQLのバージョンを9.4にアップグレードしたら、昔のプロジェクトが動かなくなってなってしまったりとか。

そこで、Dockerを使ってプロジェクト毎に環境を用意するようにすれば、そういったはまりが減らさせると思い使ってみることにしました。

Mac OS XでRailsをDocker上で動かすためのセットアップ手順をまとめときたいと思います。


## Dockerをインストール

下記を参照にインストールします。

http://docs.docker.com/installation/mac/

CUIかGUIがあるようですが、CUIの手順でインストールしていきます。GUIの場合は、Kitematicというのをいれるみたいですね。

1. [boot2docker/osx-installer](https://github.com/boot2docker/osx-installer/releases/latest)からパッケージをダウンロードします。
2. "Downloads"セクションから'Boot2Docker-x.x.x.pkg'をクリックしダウンロードします。
3. ダウンロードしたパッケージをダブルクリックしてインストールします。

これでBoot2DockerとVirtualBoxが"アプリケーション"フォルダーにインストールされます。

ターミナルを開いて、

1) 新しくBoot2Docker VMを作成します。

```
$ boot2docker init
```

これでVirtualBoxに仮想マシーンを作成します。

2) `boot2docker` VMを起動します。

```
$ boot2docker start
```

3) Dockerクライアントの環境変数を表示します。

```
$ boot2docker shellinit
Writing /Users/mary/.boot2docker/certs/boot2docker-vm/ca.pem
Writing /Users/mary/.boot2docker/certs/boot2docker-vm/cert.pem
Writing /Users/mary/.boot2docker/certs/boot2docker-vm/key.pem
    export DOCKER_HOST=tcp://192.168.59.103:2376
    export DOCKER_CERT_PATH=/Users/mary/.boot2docker/certs/boot2docker-vm
    export DOCKER_TLS_VERIFY=1
```

上記の出力はお使いの端末によって異なります。

4) お使いのシェルに環境変数をセットするには以下を実行します:

```
$ eval "$(boot2docker shellinit)"
```

私の場合はzshを使っているので、手動で上記のコマンドで出力された環境変数の箇所を`~/.zshrc`の最後に以下を追加します。

```bash:~/.zshrc
export DOCKER_HOST=tcp://192.168.59.103:2376
export DOCKER_CERT_PATH=/Users/mary/.boot2docker/certs/boot2docker-vm
export DOCKER_TLS_VERIFY=1
```

5) `hello-world`コンテナを実行してセットアップがちゃんとできてるかどうか確認します。

```
$ docker run hello-world
```


## Docker Composeのインストール

Docker Composeを使うことで複数のコンテナを効率よく管理することができます。例えば、Railsを動かすコンテナとPostgreSQLを動かすためコンテナを複数立ち上げて、それらを統一されたコマンドで操作することができます。

次のコマンドを実行してインストールします。

```
$ curl -L https://github.com/docker/compose/releases/download/1.3.3/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
```

もし、アクセス権がなくて失敗してしまう場合は、`sudo -i`をして上記のコマンドを実行して`exit`します。

## Railsのセットアップ

最後に以下を参照にしてにRails環境をセットアップしていきます。

http://docs.docker.com/compose/rails/

Composeを使ってRails/PostgreSQLの環境を構築します。

### プロジェクトの定義

プロジェクトに3つのファイルを準備します。

まず、Dockerのコンテナに必要な依存関係を定義した`Dockerfile`を作成します。

```:Dockerfile
FROM ruby:2.2.2
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
RUN bundle install
ADD . /myapp
```

ここでは、コンテナ上にRuby, Bundlerを構築する記述をしておきます。

次に、コンテナを構築した際に`bundle install`を実行するので、その際にRailsをインストールするように`Gemfile`を用意しておきます。これは、後ほど`rails new`を実行した際に上書きされます。

```
source 'https://rubygems.org'
gem 'rails', '4.2.3'
```

最後に、`docker-compse.yml`を用意して、データベースとwebアプリを構成します。

```
db:
  image: postgres
  ports:
    - "5432"
web:
  build: .
  command: bundle exec rails s -p 3000 -b '0.0.0.0'
  volumes:
    - .:/myapp
  ports:
    - "3000:3000"
  links:
    - db
```

### プロジェクトの構築

`docker-compose run`コマンドを経由して、Railsのひな形を生成します。

```bash
$ docker-compose run web rails new . --force --database=postgresql --skip-bundle
```

最初に、Composeは`Dockerfile`をベースに`web`用のをイメージを構築します。それから、その中新しいコンテナの中で`rails new`を実行します。実行が完了すると、新しくRailsのアプリが生成されていることを確認できます。

```
$ ls
Dockerfile   app          docker-compose.yml      tmp
Gemfile      bin          lib          vendor
Gemfile.lock config       log
README.rdoc  config.ru    public
Rakefile     db           test
```

`Gemfile`の`therubyracer`のコメントアウトを外します。

```
gem 'therubyracer', platforms: :ruby
```

`Gemfile`が更新されたので、イメージを構築し直します。

```
$ docker-compose build
```

### データベース接続

データベースは`db`というホスト名で動作する様に設定しています。`rails new`で生成したデフォルトでは、DBサーバはlocalhostで動作しているのを想定しているので、設定を変更します。また、`postgres`イメージで設定しているユーザ名に変更します。

`config/database.yml`を編集します。

```
development: &default
  adapter: postgresql
  encoding: unicode
  database: postgres
  pool: 5
  username: postgres
  password:
  host: db

test:
  <<: *default
  database: myapp_test
```

これでアプリを起動します。

```
$ docker-compose up
```

そうすると、いくつかのPostgreSQLの起動に関する出力に続いて、railsサーバの起動を確認できます。

```
myapp_web_1 | [2014-01-17 17:16:29] INFO  WEBrick 1.3.1
myapp_web_1 | [2014-01-17 17:16:29] INFO  ruby 2.2.0 (2014-12-25) [x86_64-linux-gnu]
myapp_web_1 | [2014-01-17 17:16:29] INFO  WEBrick::HTTPServer#start: pid=1 port=3000
```

最後に、別のターミナルを立ち上げてDBを作成します。

```
$ docker-compose run web rake db:create
```

以上で、`boot2docker ip`を実行したipに接続してRailsアプリが起動しているのを確認できます。