ある環境では動いていたのに、他の人の環境では動かなくなってしまったり、複数のプロジェクトに関わっていて、あるアプリケーションをアップグレードしたら、こっちのプロジェクトで動かなくなってしまう事が多々ありました。
gemとかであればbundler
がうまい具合に環境の差異を吸収してくれるのですが、ネイティブのライブラリを使い始めると、はまることが多くなってきます。
例えば、PostgreSQLのバージョンを9.4にアップグレードしたら、昔のプロジェクトが動かなくなってなってしまったりとか。
そこで、Dockerを使ってプロジェクト毎に環境を用意するようにすれば、そういったはまりが減らさせると思い使ってみることにしました。
Mac OS XでRailsをDocker上で動かすためのセットアップ手順をまとめときたいと思います。
Dockerをインストール
下記を参照にインストールします。
CUIかGUIがあるようですが、CUIの手順でインストールしていきます。GUIの場合は、Kitematicというのをいれるみたいですね。
- boot2docker/osx-installerからパッケージをダウンロードします。
- "Downloads"セクションから'Boot2Docker-x.x.x.pkg'をクリックしダウンロードします。
- ダウンロードしたパッケージをダブルクリックしてインストールします。
これで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
の最後に以下を追加します。
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環境をセットアップしていきます。
Composeを使ってRails/PostgreSQLの環境を構築します。
プロジェクトの定義
プロジェクトに3つのファイルを準備します。
まず、Dockerのコンテナに必要な依存関係を定義した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のひな形を生成します。
$ 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アプリが起動しているのを確認できます。