2018/9 DockerでRails環境構築
前回、Dockerの基本的な使い方をPostgreSQLを例に紹介しました。 今回は、より実践的なRails環境構築する方法を紹介します。
## プロセスポリシー ここでDockerのポリシーについて説明します。 Vagrantでは1つのVM内に、PostgreSQLとRailsを同居させて紹介しました。 しかし、Dockerでは1コンテナ・1プロセスポリシーがありPostgreSQLとRailsは別のコンテナ、つまり別のDockerfileで構築します。 このポリシーは各ソフトウェアを同居させると、同じ依存ライブラリ使うけどバージョン違うので問題が発生する。というケースを避けるためでもあるようです。準備
Dockerfile置き場作成
前回はmy_project
直下にDockerfileを配置しました。
しかし今回はPostgreSQLとRails用の2つのDockerfileを準備するので、まずDockerfile置き場を作ります。
(作らなくても動きますが、作っといたほうがわかりやすいです。)
> cd my_project
> mkdir docker_file
PostgreSQL Dockerfile作成
前回と同じ内容です。my_project/docker_file
配下にDockerfile_postgres
という名前のファイルで配置します。
FROM postgres:9.5
# 基本
ARG base_timezone="Asia/Tokyo"
ARG work_dir="/usr/local/share"
# PostgreSQL
ARG dbuser="postgres"
ARG dbpass="postgres"
ARG dbname="sample"
# 基本 ###################################
# locale設定
RUN localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG="ja_JP.UTF-8" \
LANGUAGE="ja_JP:ja" \
LC_ALL="ja_JP.UTF-8"
# timezone設定
ENV TZ="${base_timezone}"
# postgres ###################################
ENV POSTGRES_USER="${dbuser}"
ENV POSTGRES_PASSWORD="${dbpass}"
RUN echo "create database ${dbname}_development;" >> /docker-entrypoint-initdb.d/createdb.sql
RUN echo "create database ${dbname}_test;" >> /docker-entrypoint-initdb.d/createdb.sql
Rails Dockerfile作成
公式のRuby2.4イメージがベースです。 ただRailsを動かすにはNode.jsが必要です。 このRuby公式イメージにNode.jsをRUNコマンド等を使ってインストールするのもよいですが普通に手間です。
そこでDockerにはマルチステージビルドという機能を使います。
これはベースイメージに局所的に別のベースイメージを繋げて利用できます。
今回はRubyイメージに、公式Node.js v8イメージのNodeとYarnコマンドをCOPY --from=node
で連結しました。
これでNode.jsをインストールせずとも、Node.jsを利用できます。
my_project/docker_file
配下にDockerfile_rails
という名前のファイルで配置します。
FROM node:8 AS node
FROM ruby:2.4
# 基本
ARG base_timezone="Asia/Tokyo"
ARG work_dir="/usr/local/share"
ARG DEBIAN_FRONTEND=noninteractive
# Node.js
ARG yarn_version="1.9.4"
# Rails
ARG rails_version="5.1.4"
# 基本 ###################################
RUN apt-get update
RUN apt-get -y install apt-utils --no-install-recommends
# locale設定
RUN apt-get -y install locales
RUN locale-gen ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LC_CTYPE ja_JP.UTF-8
RUN localedef -f UTF-8 -i ja_JP ja_JP.utf8
# timezone設定
ENV TZ="${base_timezone}"
# Rails ###################################
# Node.js multi-stage build
COPY --from=node /opt/yarn-v${yarn_version} /opt/yarn/
COPY --from=node /usr/local/bin/node /usr/local/bin/
RUN ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn/bin/yarn /usr/local/bin/yarnpkg
# Postgresで接続
RUN apt-get install -y postgresql-client --no-install-recommends
RUN rm -rf /var/lib/apt/lists/*
# Railsインストール
RUN gem install rails --version="~>${rails_version}"
# ポート解放
EXPOSE 3000
yarnのバージョンは新しくなっているのかもしれません。 https://hub.docker.com/_/node/ からgithubのDockerfile(8/stretch/Dockerfile)のYARN_VERSIONを確認してください。
Docker Compose作成
Dockerfileが複数個ある場合、それぞれに対してdocker start
して起動するのは不便です。
そこでDocker Compose
という機能を利用して、起動・終了を一括で行えるようにします。
こちらはDockerfileとは異なりmy_project
直下にdocker-compose.yml
という名前のファイルで配置します。
version: "3"
services:
pg:
container_name: sample_pg
build:
context: ./docker_file
dockerfile: Dockerfile_postgres
ports:
- 15432:5432
rails:
container_name: sample_rails
build:
context: ./docker_file
dockerfile: Dockerfile_rails
ports:
- 3000:3000
depends_on:
- pg
links:
- pg:postgres
volumes:
- "./src:/www"
stdin_open: true
Postgre用のDockerfile_postgresを指定、ポートを15432で開放。 Railsも同様に指定し
- ポートを3000で開放
depends_on
でPostgreコンテナが起動してからRails起動するように指定links
でRailsからpostgres:5432
でPostgreSQLにアクセスできるように指定- Windows側にあるRailsソース
my_project/src
をコンテナの/www
にマウント
起動順序を指定したり、コンテナ間接続ができるのは便利ですね。
Docker Compose使い方
ビルド
PostgreSQLとRails用コンテナ作成のために一度にビルドします。
> cd my_project
> docker-compose build
操作
# 起動
> docker-compose up -d
# RailsにSSH接続(container_nameのsample_railsではなくrails)
> docker-compose exec rails bash
# コンテナ内
$ cd /www
# Rails起動
$ rails s
# コンテナ内からログアウト
$ exit
# 終了
> docker-compose stop
本当は、Rails起動する前にbundle install
したりwebpack-dev-server
起動する手順がありますが、
今回はあくまでVagrantでRails環境を構築する方法の紹介なので省きます。
構築した環境の配布
上記のように、基盤構築担当者が各Dockerfileとdocker-compose.ymlを準備します。 そして、チームメンバにDockerfileとdocker-compose.ymlを配布し
- Docker Composeビルド
- Docker Compose起動
してもらえば、あっというまに開発環境が整えられます。
最後に
DockerはVagrantに比べて記述量が少ないだけでなく
- マルチステージビルドでインストールの手間を省ける
- Docker composeで複数コンテナを一括管理・起動
- コンテナ間通信を簡単に実現
と準備の手間や保守性にも優れていることがおわかりいただけたと思います。