Rails の開発をするとき、自分の PC をなるべく汚したくないと思っていました。そんなときに役立つのが Docker です! 各ソフトは全部コンテナ側に押し込んでしまいましょう。この記事では Rails の開発環境を Docker で作成する方法を紹介します。構成を図示すると次の通り。
Docker は Linux VM 上で動かします。コンテナは次の 4 つを作成します。
- Rails Server: rails を動作させるサーバ
- Postgres: 今回採用するデータベース
- pgweb: Postgres の内容を Web で表示
- cloud9 V3 SDK: IDE
cloud9 はブラウザで開発できる IDE です。Web サービスで提供されているものだけでなく、自分の PC 上に環境を構築することができます。
注意点
以下、環境構築方法を紹介していきます。macOS での手順です。ただ、他の OS でも同じような考え方で構築できると思います。
Docker 環境の構築
Linux VM を構築しその上で Docker を動かすわけですが、簡単に構築できるツールがあります。Docker Tools です。その方法は、こちらの記事で書かせていただきました。
Docker Toolbox を使って macOS上に Docker 環境を構築する
概要をざっくり説明すると、Docker Tools とは Docker の管理に便利なツールを寄せ集めたものです。インストーラの画面の指示に従うだけで、簡単に Docker 環境を構築できます。今回使うのは次の 3 つのツールです。
- Docker Machine: Docker Engine が稼働する VM を作成したり、管理するツール
- Docker Compose: 複数コンテナを使用するDockerアプリを定義、実行するツール
- Docker QuickStart shell: macOS上のターミナルから VM 上の Docker Engine を操作するための環境整備
Docker Tools インストール後に、ランチャーパッドから「Docker QuickStart shell」のアイコンをクリックすると自動的に Linux VM が構築されます。また、その上の Docker 環境を利用するための環境変数をセットした状態で、ターミナルが起動してくれます。以降はこのターミナル上で、コンテナ構築を行っていきます。
コンテナ作成の準備
今回作成するコンテナを改めて書くと次の 4 つになります。
- Rails Server: rails を動作させるサーバ
- Postgres: 今回採用するデータベース
- pgweb: Postgres の内容を Web で表示
- cloud9 V3 SDK: IDE
このうち、Postgres, pgweb は公開されているイメージをそのまま使います。Rails Server, cloud9 は Dockerfile を作成しビルドします。
ディレクトリ、ファイル構成
以下の構成にします。
|- docker-compose.yml Docker Compose の設定ファイル
|- Dockerfike-web Rails Server 用の Dockerfile
|- Dockerfile-cloud9 cloud9 V3 SDK 用の Dockerfile
|- src/ Rails のソース類を配置するディレクトリ
|- Gemfile Rails Server の bundle 用
|- Gemfile.lock Rails Server の bundle 用
Rails のソースは src に配置し、ここをコンテナ側からも参照できるようにします。
Dockerfile の内容
Rails Server
Rails Server 用の Dockerfile です。今回は、複数の Dockerfile を作成するため、ファイル名にサフィックスをつけて用途が分かるようにしておきます。
FROM ruby
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
ENV BUNDLE_JOBS=4 \
APP_DIR=/app
RUN mkdir $APP_DIR
WORKDIR $APP_DIR
COPY src/Gemfile $APP_DIR
COPY src/Gemfile.lock $APP_DIR
RUN bundle install
cloud9
cloud9 用の Dockerfile です。Cloud9 Core のインストール手順に習っています。
FROM node
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
RUN git clone https://github.com/c9/core.git /cloud9
WORKDIR /cloud9
RUN ./scripts/install-sdk.sh
WORKDIR /workspace
[memo] 私の環境だと、4 行目の install-sdk.sh 内の処理で npm install に失敗しました。registry.npmjs.org にアクセスできない旨のエラーメッセージ。macOS 側の DNS にルータのアドレスが設定されていたのですが、8.8.8.8 にすることで改善しました。
docker-compose.yml
以下の内容にします。
version: '3'
services:
postgres:
image: postgres
volumes:
- postgres-data:/var/lib/postgresql/data
postgres-gui:
image: donnex/pgweb
command: -s --bind=0.0.0.0 --listen=8080 --url postgresql://postgres@postgres/myapp_development?sslmode=disable
ports:
- "7000:8080"
depends_on:
- postgres
web:
build:
context: .
dockerfile: Dockerfile-web
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- ./src:/app
- bundle-data:/usr/local/bundle
ports:
- "3000:3000"
depends_on:
- postgres
cloud9:
build:
context: .
dockerfile: Dockerfile-cloud9
command: node /cloud9/server.js --port 80 -w /workspace -l 0.0.0.0 --auth user:password
ports:
- 9000:80
volumes:
- ./src:/workspace
- cloud9-data:/cloud9
volumes:
postgres-data:
bundle-data:
cloud9-data:
ポイントは次の通りです。
- 永続化するデータは volumes で指定します。コンテナを削除しても残っています。
- 起動順序は depends_on で指定します。ただ、この方法だと、コンテナ上のサービス起動が完了していることが保障されません。保障する方法はこの記事では対象外とします。
Gemfile
Rails Server の bundle 用です。下記内容にします。
source 'https://rubygems.org'
gem 'rails', '5.1.4'
空にする。
コンテナのビルド
上記ファイルの準備ができたら、ビルドを実行します。数十分程度かかります。
$ docker-compose build
このコマンドを実行すると、次の内容の処理が実行されます。
- Dockerfile の内容に従ってイメージのビルド。
2018年2月3日時点ではここまで書いた手順でうまくいっています。なお、イメージのビルドは、PC 環境の違いやバージョン違いなどの理由ですんなり通らないことも多いので、トライアンドエラーで頑張らないといけない場合も結構あります。
Rails アプリケーションの作成
では、早速できたイメージからコンテナを起動し、rails new で Rails アプリケーションを作成します。
$ docker-compose run --rm web rails new . --force --database=postgresql
処理が終わると rails new で作られたファイル群が src ディレクトリの下に出来ます。
$ ls src/
Gemfile README.md app config db log public tmp
Gemfile.lock Rakefile bin config.ru lib package.json test vendor
DB との連携のため、rails の設定ファイルを編集します。
default: &default
adapter: postgresql
encoding: unicode
host: postgres
username: postgres
password:
pool: 5
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
DB を作成しておきます。
$ docker-compose start postgres
$ docker-compose run --rm web rails db:create
コンテナを起動
コンテナを起動します。
$ docker-compose up
# バックグラウンドで起動する場合は -d オプションをつけます。
$ docker-compose up -d
では、表示確認をしてみましょう。
Rails Server
http://192.168.99.100:3000 にアクセスすると、Rails のページを表示できます。
pgweb
http://192.168.99.100:7000 にアクセスすると、pgweb のページを表示できます。
cloud9 v3 SDK
http://192.168.99.100:9000 にアクセスすると、cloud9 のページを表示できます。ユーザ名は「user」、パスワードは「password」です。
よく使う Docker Compose コマンド
Rails 関連
rails コマンドはコンテナを起動して実行します。
// db:migrate
$ docker-compose run --rm web rails db:migrate
// テスト
$ docker-compose run --rm web rails test
コンテナ稼動に関するもの
稼動状況の確認
$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------
rails_cloud9_1 node /cloud9/server.js --p ... Up 0.0.0.0:9000->80/tcp
rails_postgres-gui_1 /app/pgweb_linux_amd64 -s ... Up 0.0.0.0:7000->8080/tcp
rails_postgres_1 docker-entrypoint.sh postgres Up 5432/tcp
rails_web_1 bundle exec rails s -p 300 ... Up 0.0.0.0:3000->3000/tcp
コンテナ上で動作しているプロセスの表示
$ docker-compose top
一時停止
$ docker-compose stop
停止したコンテナの削除(volume で永続化したデータは残ります)
$ docker-compose rm
Going to remove rails_web_1, rails_postgres-gui_1, rails_postgres_1, rails_cloud9_1
Are you sure? [yN] y ← y を入力し [Enter]
ボリュームの削除
// 一覧の表示
$ docker volume ls
// 削除
$ docker volume rm [ボリューム名]
参考
Quickstart: Compose and Rails
Cloud9 Core
修正履歴
2018/2/24: いくつか誤りがあったので、修正しました。