LoginSignup
51
67

More than 3 years have passed since last update.

【入門】DockerでRuby on Rails + PostgreSQL + React + TypeScriptな環境をビルド

Last updated at Posted at 2018-11-15

背景

今まで何度かDockerに触ろうとしては挫折してきました。Dockerを学ぶ難しさは、どの入門記事を見ても書いてあることが違う、その通りに書いても何らかのエラーが出て止まる、どこを参考にすればいいのか分からない、といったところにあると思います。半ば学ぶことを諦めていたのですが、ある時「Dockerは現代サーバーサイドエンジニアの必須科目だ」と言われてしまい、もう一度挑戦してみた時の記録です。

対象読者

  • 「Dockerって何? docker-compose って何?」な読者
  • 「とりあえず自分のプロジェクトをDockerで動かしてみたい」な読者

参考

環境

$ docker -v
Docker version 18.06.0-ce
$ docker-compose -v
docker-compose version 1.22.0

前提

  • Dockerのインストールについては他記事を参照。

はじめに

Dockerとは

Dockerは「コンテナ」という技術を用いて環境構築を助けてくれるツールです。通常、アプリケーションの開発環境を用意する際、自分のPCのローカル環境が他の開発者のローカル環境と差がある場合があり、その差に起因して同じ手順での環境構築がうまくいかなかったりします。それを防ぐために、DockerがPCの中に全く新しい別の仮想的なコンピュータを作ってくれます。その作り方の手順を Dockerfile というファイルに記述して他の開発者に配布することで、皆が同じ環境を作ることができるということです。

docker-composeとは

Dockerは1つの仮想的なコンピュータを立ち上げ、その中でアプリケーションを動かします。しかし実際の開発現場では、複数のアプリケーションを必要とすることが多いです。例えばRailsなら、APIサーバーにRails、DBサーバーにPostgreSQL、フロントエンドにReactといったように。
Dockerでこれらを構築しようとすると、1つのDockerfileで1つのサーバーを担当することになります。そこで、その複数のDockerがどのように関連・構成されているのかを定義する役割を負うのが docker-compose です。その構成の定義ファイルが docker-compose.yml になります。

手順

それでは実際に Docker / docker-compose を用いて Rails + PostgreSQL + React の構成で開発環境を構築してみましょう。

ディレクトリ構成

下記のような構成でアプリケーションを構築していきます。

. # プロジェクトルート
|- api   # Railsアプリケーションを置くディレクトリ
|- front # Reactアプリケーションを置くディレクトリ
|- docker-compose.yml # アプリケーションの構成を定義するファイル

事前準備

Railsプロジェクトを生成

$ rails new api --api -d postgresql

データベースへの接続情報を記述する

api/config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password:
  pool: 5

development:
  <<: *default
  database: api_dev

test:
  <<: *default
  database: api_test

production:
  <<: *default
  database: api_production
  username: api
  password: <%= ENV['API_DATABASE_PASSWORD'] %>

gemをインストール

$ bundle install --path vendor/bundle

普通に bundle exec rails s で起動できる状態にしておく。

React + TypeScriptプロジェクトを生成

$ npm install -g create-react-app
$ create-react-app front --scripts-version=react-scripts-ts

普通に npm start で起動できる状態にしておく。

Rails用のDockerfileを用意

Railsプロジェクトのルートに下記のDockerfileを設置する。

api/Dockerfile
FROM ruby:2.5.1

WORKDIR /app
COPY Gemfile /app
COPY Gemfile.lock /app
COPY . /app

RUN apt-get update -qq && apt-get install -y build-essential nodejs libpq-dev postgresql-client
RUN gem update bundler && bundle install

解説

  • FROM ruby:2.5.1 : 公式が用意した既存のRuby 2.5.1用の環境をテンプレートとしてダウンロードする。
  • WORKDIR /app : コンテナ内のワーキングディレクトリを /app に設定する。
  • COPY Gemfile /app : ホスト側のGemfileをコンテナ側の/appディレクトリ内にコピーする。
  • COPY Gemfile.lock /app : ホスト側のGemfile.lockをコンテナ側の/appディレクトリ内にコピーする。
  • RUN apt-get update -qq && apt-get install -y build-essential nodejs libpq-dev postgresql-client : Railsの起動に必要なライブラリを apt-get 経由でインストールする。
  • RUN gem update bundler && bundle install : gemをインストールする。

React用のDockerfileを用意

front/Dockerfile
FROM "node:6-alpine"

WORKDIR /app

docker-composeを定義

docker-compose.yml
version: '3.5'

services:
  db:
    image: postgres:10.4
    volumes:
      - postgres-data:/var/lib/postgresql/data
  api:
    build: ./api
    command: /bin/sh -c "rm -f /app/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    image: rails:dev
    volumes:
      - ./api:/app
      - ./api/vendor/bundle:/app/vendor/bundle
    environment:
      TZ: Asia/Tokyo
      RAILS_ENV: development
    ports:
      - 3000:3000
    depends_on:
      - db
  front:
    build: ./front
    command: yarn start
    volumes:
      - ./front:/app
    ports:
      - 8000:3000
volumes:
  postgres-data:
    driver: local

解説

  • docker-compose は1つのDockerをserviceという単位で管理する。
  • 今回はPostgreSQL用のサーバーを db 、Rails用のサーバーを api 、React用のサーバーを front と名付けて設定していく。
  • PostgreSQLは公式が用意した postgres という環境(イメージ)があれば、追加でインストールすべきもの等も特に無い。そのためDockerfileを用いず、docker-composeにイメージ名を指定するだけで環境を構築できる。
  • RailsとReactについてはDockerfileを用意したので、それぞれ build という項目にDockerfileの位置を記入する。
  • command : 実際にサーバーを起動する時のコマンドを記述する。Rails起動時に rm -f /app/tmp/pids/server.pid が挟まっているのは、 docker-compose を停止する度に server.pid が削除されないまま残ってしまう問題に対処するため。
  • volumes : 記憶領域の指定。ディレクトリ名で指定するパターンと、ボリューム名で指定するパターンがある。ボリューム名を用いる場合は最後に出てくる volumes を用いる。ディレクトリ名で指定する場合、 <ホスト側のディレクトリ>:<対応するコンテナ側のディレクトリ> と書けば、ホスト側でファイルが変更された時にコンテナ側にすぐ反映されるようになる。
  • environment : 環境変数の設定。プロパティ名だけ書いて値を書かなければ、コンテナ起動時のホスト側の環境変数が自動で引き継がれるため、SECRET等はこのような方法でコンテナに渡す。
  • posts : ホストからのアクセスをコンテナ側へ渡すプロキシを設定する。例えば 8000:3000 なら、ホスト側が localhost:8000 でアクセスしてきた場合、コンテナ側の localhost:3000 に渡す。これでコンテナ内のアプリケーションにアクセスできるようになる。
  • depends_on : 依存関係を設定する。今回の場合、例えばRailsだけを起動しようとしても、依存関係のあるdbも自動で一緒に起動される。

起動

$ docker-compose build
$ docker-compose run front yarn
$ docker-compose run api bundle exec rails db:create
$ docker-compose up

解説

  • docker-compose build : Dockerfileを読み込んで必要なイメージをダウンロード&構築
  • docker-compose run <コマンド> : コンテナ側のワーキングディレクトリ上で <コマンド> を実行
  • docker-compose up : servicesに定義された各コンテナを起動
  • docker-compose stop : servicesに定義された各コンテナを停止

Reactアプリケーションが http://localhost:8000 、Railsアプリケーションが http://localhost:3000 で起動するはず。

51
67
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
51
67