はじめに
Rails学習の一歩として、最初に取り組んだのはコンテナ環境の構築でした。予想以上に時間と労力がかかりましたが、何とか構築することができ、その結果、Dockerのスキルが大いに向上しました。環境構築やDockerスキルの向上を目指している方々に、少しでも参考になれば幸いです。Railsを学び始めた時の書籍が、「Rails5」「PostgreSQL10」を用いた環境のため、そこに焦点を当て環境構築を行いました。
Dockerスキルアップのコツ
Dockerのスキルアップのコツは慣れです。同じコマンドや環境を何度も実行/構築することでスキルアップにつながります!暗記しようとせずに、慣れていきましょう!
また、これらはRailsやPostgresのバージョンが異なっていても、同様な考え方でコンテナ環境を構築できます。設定はバージョンごとに異なるかと思いますが、その都度調査することで、Dockerのスキルアップに繋がるため、ぜひチャレンジしてみてください!
準備
まずは、「ローカル環境のフォルダ」
「Dockerfile」
「docker-compose.yml」
「Gemfile」
「Gemfile.lock」
を作成します。
ローカル環境のフォルダ
handsonというフォルダを作成し、その中にDockerfile、docker-compose.yml、Gemfile、Gemfile.lockを作成して、それぞれ後述のコードをコピペします。
Dockerfile
Dockerfile
はDockerイメージのビルド手順を定義します。
-
FROM ruby:2.5.1
- Ruby 2.5.1がインストールされたDockerイメージを指定します。
-
RUN echo "deb http://archive.debian.org/debian/ stretch main" > /etc/apt/sources.list \ ...
- Debianのパッケージリポジトリを設定し、build-essentialとnodejsをインストールします。build-essentialはCコンパイラなどのビルドに必要なパッケージをまとめたものです。nodejsはJavaScriptの実行環境です。
-
RUN mkdir /app
- Dockerコンテナ内に/appというディレクトリを作成します。
-
WORKDIR /app
- 作業ディレクトリを/appに変更して、以降の命令は/appから実行されます。
-
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
- ホストのGemfileとGemfile.lockをコンテナの/appディレクトリにコピーします。
-
RUN bundle install
- Gemfileに記載されたgemをインストールします。
-
COPY . /app
- ホストの現在のディレクトリの全てのファイルをコンテナの/appディレクトリにコピーします。
FROM ruby:2.5.1
RUN echo "deb http://archive.debian.org/debian/ stretch main" > /etc/apt/sources.list \
&& echo "deb http://archive.debian.org/debian-security stretch/updates main" >> /etc/apt/sources.list \
&& apt-get update -qq && apt-get install -y build-essential nodejs
RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY . /app
docker-compose.yml
docker-compose.yml
は複数のコンテナ間の関係を定義します。
-
version: '3'
- docker-composeのバージョンを指定しています。
-
services:
- webとdbの2つのサービス(コンテナ)を定義しています。
-
web:
- webサービス(コンテナ)の設定を始めることを示します。
-
build: .
- 現在のディレクトリ(.)にあるDockerfileに基づいてDockerイメージをビルドします。
-
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
- コンテナが起動する際に実行されるコマンドを指定します。ここでは、まず既存のserver.pidファイルを削除し(存在すれば)、その後Railsサーバを起動します。
-
volumes: - .:/app
- ホストの現在のディレクトリ(.)とコンテナ内の/appディレクトリをマウントします。ホストとコンテナ間でファイルが共有されます。
-
ports: - 3000:3000
- ホストの3000番ポートとコンテナの3000番ポートをマッピングします。ホストのブラウザからhttp://localhost:3000でRailsアプリケーションにアクセスできます。
-
depends_on: - db
- webサービスがdbサービスに依存していることを示します。dbサービスが先に起動した後でwebサービスが起動します。
-
tty: trueとstdin_open: true
- これらのオプションはコンテナ内での対話型プロセスを可能にします。
-
db:
- dbサービス(コンテナ)の設定を始めることを示します。
-
image: postgres:10.1
- バージョン10.1のPostgreSQLイメージ(Dockerイメージ)を使用します。
-
volumes: - postgres_volume:/var/lib/postgresql/data
- 名前付きボリュームpostgres_volumeとコンテナ内の/var/lib/postgresql/dataディレクトリをマウントすることで、データベースのデータが永続化されます。
-
environment: POSTGRES_PASSWORD: password
- 環境変数を設定します。ここではPostgreSQLのパスワードをpasswordとしています。
-
ports: - 5432:5432
- ホストの5432番ポートとコンテナの5432番ポートをマッピングします。
-
restart: always
- コンテナが何らかの理由で終了した場合、Dockerが自動的にコンテナを再起動します。
-
volumes: postgres_volume:
- 名前付きボリュームpostgres_volumeの設定を始めることを示します。
version: '3'
services:
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/app
ports:
- 3000:3000
depends_on:
- db
tty: true
stdin_open: true
db:
image: postgres:10.1
volumes:
- postgres_volume:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
restart: always
volumes:
postgres_volume:
Gemfile
GemfileはRubyのプロジェクトで使用するgem(ライブラリ)を管理するためのファイルです。
-
source 'https://rubygems.org'
gemの取得元となるソースを指定しています。ここでは公式のRubyGemsリポジトリからgemを取得します。 -
gem 'rails', '~> 5.2.0'
rails gemのバージョンを5.2.xと指定しています。この記述により、bundle installコマンドを実行したときにRailsのバージョン5.2.xがインストールされます。
source 'https://rubygems.org'
gem 'rails', '~> 5.2.0'
Gemfile.lock
Gemfile.lockはRubyのプロジェクトで使われるライブラリ(gem)のバージョンを記録するファイルです。Gemfile.lockがあることで、同じプロジェクトでも異なる環境で実行したときに同じgemのバージョンが使われ、挙動の違いを防げます。ただし、新しいRailsプロジェクトを作成する際には、まだどのgemを使用するか、それらのバージョンが決まっていないため、Gemfile.lockは空
にします。その後、bundle installが初めて実行されるとき、Gemfile.lockにはGemfileに記述されたgemのバージョンが自動的に記録されます。
docker-composeコマンド
docker-compose
を実行して、Rails5のコンテナ環境を構築します。
はじめに、docker-compose run
コマンドを実行して、Railsアプリケーションの初期セットアップを行います。
-
web
docker-compose.yml ファイル内のサービス名を指しています。 -
rails new .
新しいRailsアプリケーションを現在のディレクトリ(.が現在のディレクトリを示します)に生成するためのコマンドです。 -
--force
ファイルがすでに存在していた場合でも、強制的に新しいRailsアプリケーションを生成するためのオプションです。つまり、すでにあるファイルは新しいもので上書きされます。 -
--database=postgresql
新しいRailsアプリケーションのデータベースとしてPostgreSQLを使用するように設定するためのオプションです。
docker-compose run web rails new . --force --database=postgresql
docker-compose build
コマンドを実行して、Dockerfileからイメージをビルドします。
docker-compose build
docker-compose up -d
コマンドを実行して、コンテナをバックグラウンド(-dオプション)で起動します。
docker-compose up -d
この段階ではまだエラーになるため、データベースの設定を行います。
Railsのconfig/database.ymlを編集します。
default: &default
~~~~省略~~~~~~
~~~~以下の3行を追加~~~~~~
host: db
username: postgres
password: password
~~~~~~~~~~
docker-compose run
コマンドを実行して、データベースを作成します。
docker-compose run web rails db:create
docker-compose restart
コマンドを実行して、コンテナを再起動します。
docker-compose restart
localhost:3000にアクセスして、Railsのデフォルトページが表示されれば成功です。
docker-compose stop
コマンドを実行して、コンテナを停止します。
docker-compose stop
localhost:3000にアクセスして、表示されないことを確認します。
不要なコンテナやイメージを削除する
これまでの操作を行なっていくと、「dockerコンテナ」「dockerイメージ」が複数作成されているかと思います。
handson % docker-compose ps -a
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
handson-db-1 postgres:10.1 "docker-entrypoint.s…" db 23 minutes ago Exited (0) 10 seconds ago
handson-web-1 handson-web "bash -c 'rm -f tmp/…" web 10 minutes ago Exited (1) 10 seconds ago
handson-web-run-7188bd29e0ec handson-web "rails db:create" web 2 minutes ago Exited (0) About a minute ago
handson-web-run-eb881b1d471e sha256:6ff7a599ebf79862b6f97c4c8af0f53c8422400632514855d24ae26ab637714c "rails new . --force…" web 23 minutes ago Exited (0) 22 minutes ago
handson % docker-compose images
CONTAINER REPOSITORY TAG IMAGE ID SIZE
handson-db-1 postgres 10.1 ec61d13c8566 287MB
handson-web-1 handson-web latest 8e1e773be953 1GB
handson-web-run-7188bd29e0ec handson-web latest 8e1e773be953 1GB
handson-web-run-eb881b1d471e <none> <none> 6ff7a599ebf7 972MB
docker-compose up -d
を実行したときに作成されるコンテナは以下の2つです:
handson-web-1:
Railsアプリケーションをホストするコンテナで、Dockerfileからビルドされたイメージruby:2.5.1を使用します。docker-compose.ymlファイルのwebサービスに対応しています。
handson-db-1:
PostgreSQLデータベースをホストするコンテナで、公式のPostgreSQLイメージpostgres:10.1を使用します。docker-compose.ymlファイルのdbサービスに対応しています。
これらの2つのコンテナが起動しているため、Railsアプリケーションはブラウザからアクセス可能になっています。
Railsアプリケーションがブラウザからアクセス可能になるのは、rails1-web-1とrails1-db-1という2つのコンテナが起動しているからです。その他のコンテナやイメージは一時的に作成されたもので、Railsアプリケーションの動作には直接影響しません。
そのため、以下のコマンドでコンテナ、イメージを削除します。
コンテナを削除
不要なコンテナを削除する。
docker rm handson-web-run-7188bd29e0ec
イメージを削除
不要なイメージを削除する。
docker rmi 6ff7a599ebf7
全てのリソースを削除
全ての作業が完了し、利用が終わり、不要になった場合は、docker-compose down --rmi all --volumes --remove-orphans
コマンドを実行して、コンテナ、ネットワーク、イメージ、ボリュームを削除できます。
docker-compose down --rmi all --volumes --remove-orphans
まとめ
環境構築の流れをまとめました。
# コンテナ作成の前準備
「ローカル環境のフォルダ」 「Dockerfile」 「docker-compose.yml」 「Gemfile」 「Gemfile.lock」を作成
# Railsアプリケーションのコンテナ環境を構築
docker-compose run web rails new . --force --database=postgresql
docker-compose build
docker-compose up -d
~~ database.ymlを編集 ~~
docker-compose run web rails db:create
docker-compose restart
docker-compose stop
docker-compose down --rmi all --volumes --remove-orphans
# 不要なコンテナ、イメージを削除したい場合
docker rm ${コンテナ}
docker rmi ${イメージ}