はじめに
今回はDocker公式のクィックスタート: Compose と Railsというページを参考にDocker Composeを使ってRailsアプリ+Postgresのdocker化に挑戦したので、その方法を説明していきます。
初学者による説明なので、ご注意ください。
対象読者
-
クイックスタートの例をそのまま実施したが、うまくいかない人
-
Rails+PostgresのDocker化の手順をなんとなく知りたい人
-
三日前の自分
バージョン
クイックスタートのままのバージョンで実施するとあれやこれやとエラーになってしまったので、バージョンを下記のように設定しています。
-
Ruby 3.2.2
-
Rails 7.1.x
-
Postgres version 12
RubyとRailsのバージョンの組み合わせは下記を参考にして選びました。
参考:
筆者の環境
-
macOS Sequoia 15.3
-
Apple M2
1.Railsアプリのdocker化に必要なファイルを4つ作成
まずはRailsアプリを構成するファイルとdocker化に必要なファイルを用意します。
以下の4つのファイルが必要です。
-
Dockerfile
-
Gemfile
-
Gemfile.lock
-
docker-compose.yml
それぞれ説明していきます。
Dockerfile
Dockerイメージを作成するために、Dockerfileを記述します。
下記のように記述します。
ここでは、クイックスタートのコードからruby:3.2.2に変更しています。
FROM ruby:3.2.2
RUN apt-get update -qq && apt-get install -y \
build-essential \
libpq-dev \
nodejs
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp
apt-get update
-
最新のパッケージリストをソフトウェアの配布元から取得する
-
システムのパッケージ情報を最新の状態にする
-
-qqオプション
- ログを極力表示させない
apt-get install
- パッケージ名を指定してインストールする
Gemfile
以下のように記述します。
ここでは、クイックスタートのコードから7.1に変更しています。
source 'https://rubygems.org'
gem 'rails', '7.1'
Gemfile.lock
空のGemfile.lockファイルを作成します。
DockerfileをDockerイメージにビルドするために記述します。
docker-compose.yml
Railsを動かすコンテナとPostgresを動かすコンテナが2つありますが、本来、ネットワークを作成したり色々設定しないとコンテナ間の接続ができません。
docker composeという仕組みのおかげで、一つのdocker composeの中にある複数のコンテナは設定不要でコンテナ間通信ができるようになります。
docker-compose.ymlは下記のように記述します。
ファイル名がdocker-compose.ymlではなく、compose.yamlが公式推奨ですが、今回はクイックスタートの例で進みます。
加えて、version: ‘3’というのも不要で、残したままコマンドを実行すると警告が出ますが、同様にこのまま進めます。
version: '3'
services:
db:
image: postgres:12
environment:
- 'POSTGRES_PASSWORD=postgres'
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
個人的に重要なプロパティだけ説明します。
environment
環境変数を追加できます。
POSTGRES_PASSWORD
の記述を忘れるとエラーになります。
ここの値が重要で、下記のような記述がGitHubのdocsにありました。
PostgreSQL イメージでは、見逃しやすい環境変数がいくつか使用されます。必須の変数は のみで
POSTGRES_PASSWORD
、残りはオプションです。
参考:
2.Railsアプリの雛形を作成
docker-compose run web rails new . --force --database=postgresql
とターミナルに入力します。
すると、Railsアプリに必要なファイルが作成されます。
3.Dockerイメージを再ビルド
先ほどのコマンドを入力すると、DockerfileとGemfileに変更が入ります。
docker-compose build
とターミナルに入力して、Dockerイメージを作ります。
web BuiltとなればOKです。
4.データベースの接続設定
config/database.yml はdefault部分だけ修正します。
default: &default
adapter: postgresql
encoding: unicode
host: db # 追加
username: postgres # 追加
password: postgres # 追加
adapter
- データベースの種類を指定
host
- データベースが動作しているホスト名(コンテナ名)を指定
次に、config/database.ymlを書き換えたら
docker-compose up
と入力します。
ここで、RubyとRailsのバージョンが古かったり、新しすぎたり、組み合わせが悪かったりするとエラーになることが多かったです。
なんかエラーになった!
なので、docker-compose.ymlのwebのプロパティに以下を追加します!
RAILS_ENV=development
そして、再度、docker-compose up
を入力して
下図のような表示になったらOKです。
ちなみにdocker-compose up -d
と入力してバックグラウンドでコンテナを起動すると 別タブへ移動する必要がありません。
その後、ターミナルで新規タブを開き、下記を入力します。
docker-compose run web rake db:create
まだダメのようです。
コマンドの言う通り、bundle execを頭につけて実行します。
docker-compose run web bundle exec rake db:create
色々調査したところ、rails newを入力したときに、Dockerfileの記述の中で WORKDIRが/railsになっていました。
前述の通り、docker-compose.ymlファイルはホストのカレントディレクトリを/myappにマウントするよう設定しています。
そのため、database.ymlのhost: dbという設定が反映されず、Postgresのコンテナに接続できなかったのでは?と思いました。
しかし、直前でdocker-compose run
であったり、Dockerfile内にCOPY . .
などしていて、更新はされているものと思いましtおそらくキャッシュされたイメージがビルドされたのかなーと勝手に思っています。
また、一つ前のエラーでRAILS_ENV=”development”
にしましたが、Dockerfileを見るとRAILS_ENV=”production”
と記載されており、これが原因だったようですね。
と、初学者による考えは置いておいて、本題へ戻ります。
-
Dockerfileをもともと作成したファイルに上書きして・・・
-
docker-compose build
を入力・・・ -
docker-compose up
を入力・・・ -
docker-compose run web bundle exec rake db:create
を入力すると・・・
ようやくデータベースが出来ました!
5.RailsのWelcomeページを確認する
localhost:3000にアクセスしましょう!
無事、日の丸を拝むことができました!
終わりに
今回はクイックスタートの例を元にDocker Composeを使ったRails+PostgresのDocker化について説明しました。
いくつかエラーを紹介しましたが、ここに載せ切れないくらいのエラーを経験しました。今回の演習を通して、Docker Composeの使い方だけでなく、エラーとの向き合い方を知り、エラーが出てもめげない精神はついたのかなと思います!
もちろんまだまだ実務レベルには程遠いと思うので、これからも精進します!
参考