はじめに
Railsの環境構築、甘く見てました。
Docker × Rails × PostgreSQL の組み合わせでアプリを立ち上げるまで、
何度も地雷を踏み、何度もエラーに泣かされ、何度も心が折れかけました。
この記事では、そんな僕が実際に踏んだエラーとその解決策を含めて、
初期構築からサーバー起動までの手順を完全にまとめました。
「最短で立ち上げたい」
「もうハマりたくない」
そんな人の役に立てたら嬉しいです。
実施したこと
要約
既存のRailsアプリをGitHubからクローンし、Docker ComposeとPostgreSQLを使ってDocker環境を構築しました。
詳細
- GitHubのテンプレートから docker_rails リポジトリを作成
- 作成したリポジトリをローカルにクローン
- ローカルで
docker
ブランチを作成し変更 - 以下のファイルを新規作成・編集し、Docker環境を構築
- 新規作成
Dockerfile
Gemfile
Gemfile.lock
docker-compose.yml
- 編集
config/detabase.yml
- 新規作成
-
docker compose up --build
でアプリを起動し、ブラウザで表示を確認 - 変更内容を GitHub にプッシュし、プルリクエストを作成
開発環境
- macOS Sequoia
- Docker version 28.3.2
- Docker Compose version v2.38.2
- ruby 3.4.5
- Rails 8.0.2
- PostgreSQL version 12
ファイル構成
rails_docker/
├── .github/workflows/docker.yml
├── Dockerfile
├── docker-compose.yml
├── Gemfile
├── Gemfile.lock
├── config/
│ ├── application.rb
│ ├── boot.rb
│ ├── database.yml
│ └── environment.rb
完成形を見たい方はこちら
すぐに動くコードだけ見たい方は、以下を参考にしてください。
完成系はこちら
Docker環境構築手順とエラー対応
Docker環境構築手順
1. 事前準備フェーズ:環境確認とリポジトリ準備
2. 基礎ファイル作成フェーズ:構築ファイルの準備
3. DB設定フェーズ:接続設定
エラー対応フェーズ
4. secret_key_base エラー
5. bootsnap/setup 読み込みエラー
6. config.assets 関連エラー(Rails8非対応設定)
7. postgresql アダプタ読み込みエラー(pg gem不足)
8. puma gem不足エラー
9. migrate未実行エラー
10. javascript_importmap_tags 未定義エラー
Docker環境構築手順とエラー対応詳細
1. 事前準備フェーズ:環境確認とリポジトリ準備
まずは、Docker と Docker Compose がインストールされているかを確認します。
docker -v
docker compose version
続いて、GitHub から Rails アプリをローカルにクローンします
git clone https://github.com/rai-code11/rails-docker.git
Gitは リポジトリ名と同じ名前のフォルダ rails-docker/ を自動生成してその中にクローンしますが、下記のようにディレクトリを指定すると任意のディレクトリ名をつけそこにクローンすることができます
git clone https://github.com/rai-code11/rails-docker.git rails_docker
これでrails_docker/
という名前のディレクトリができ、そこが.git
を含むクローン先になります
rails_docker
ディレクトリに移動します
cd rails_docker
docker
ブランチを切ってブランチを変更します
git checkout -b ブランチ名
現在のブランチを確認するには、以下のコマンドを使用します
git branch
2. 基礎ファイル作成フェーズ:構築ファイルの準備
以下のコマンドで、必要なファイルを作成します
touch Dockerfile Gemfile Gemfile.lock
まずdockerfile
から記述します
code Dockerfile
Dockerfile
アプリケーションを動かすための環境(OS・ライブラリなど)を定義したファイル。コンテナを作るための設計書です。
FROM ruby:3.4.5
RUN apt-get update -qq && apt-get install -y \
nodejs \
postgresql-client \
yarn
WORKDIR /rails_docker
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
-
FROM
:どのイメージを使うか?
今回はRuby 3.4.5 の公式イメージを使って、アプリの土台を作ります。 -
RUN
:ベースイメージ(例:ruby:3.4.5)から一時的なコンテナを作り、その中で RUN に書かれたコマンドを実行します。実行結果(ファイル変更など)を「新しいイメージのレイヤー」として保存し、コンテナから抜けます。-
今回実行されるコマンド
-
apt-get update -qq
- apt-get update
- 最新のパッケージリストを取得します
- -qq(quiet quiet)
- 通常の apt-get update は大量にミラーURLや取得情報を表示するが、-qq だと必要最低限しか出ません
- apt-get update
-
apt-get install -y
-
apt-get install
- 指定したパッケージをインストールする
-
今回必要なパッケージ
-
nodejs
:JavaScript動作用(RailsでJSを使う) -
postgresql-client
:PostgreSQLに接続するためのクライアントツール -
yarn
:JavaScriptパッケージ管理ツール(Webpackerやjsbundlingで使用)
-
-
今回必要なパッケージ
- 指定したパッケージをインストールする
-
-y
- インストール時の「続行しますか? [Y/n]」という確認を自動的にYesで回答
- Dockerビルドは非対話的に進める必要があるため必須です
-
-
下記のように
&&
でコマンド同士を繋げることができます
RUN apt-get update -qq && apt-get install -y
-
-
-
WORKDIR /rails_docker
これ以降のコマンドを/rails_dockerディレクトリで動作させる設定です -
COPY Gemifile Gemfile.lock ./
GemifileとGemfile.lockファイルをコンテナの/rails_dockerディレクトリにコピーします -
RUN bundle install
Gemツールをインストールします -
COPY . .
ホストのカレントディレクトリをコンテナ内の/rails_dockerファイル内にコピーします
補足
RubyとRailsのバージョンの互換性はこちらで確認できます
railsの最新バージョン確認コマンド
RubyGems.org に公開されている "rails" という名前の gem の全バージョン一覧を取得するためのコマンド
gem search ^rails$ --remote --all
コマンドの意味
-
gem search
RubyGems にある gem を検索するコマンド。 -
^rails$
「行の先頭から末尾までが ちょうど rails だけのものに一致」-
^
→ 文字列の先頭-
^rails
「railsで始まる」すべての文字列が一致
-
-
rails
→ 検索対象文字列 -
$
→ 文字列の末尾-
rails$
「railsで終わる」すべての文字列が一致
-
-
-
--remote
ローカルにインストールされている gem ではなく、RubyGems.org(リモート)上で検索するという指定。 -
--all
対象 gem のすべてのバージョンを表示するオプション。
これがない場合は最新の安定版しか表示されない。
表示結果
*** REMOTE GEMS ***
rails (8.0.2, 8.0.1, 8.0.0.1, 8.0.0, 7.2.2.1, 7.2.2, 7.2.1.2, 7.2.1.1, 7.2.1, 7.2.0, 7.1.5.1, 7.1.5, 7.1.4.2, 7.1.4.1, 7.1.4, 7.1.3.4, 7.1.3.3, 7.1.3.2, 7.1.3.1, 7.1.3, 7.1.2, 7.1.1, 7.1.0, 7.0.8.7, 7.0.8.6, 7.0.8.5, 7.0.8.4, 7.0.8.3, 7.0.8.2, 7.0.8.1, 7.0.8, 7.0.7.2, 7.0.7.1, 7.0.7, 7.0.6, 7.0.5.1, 7.0.5, 7.0.4.3, 7.0.4.2, 7.0.4.1, 7.0.4, 7.0.3.1, 7.0.3, 7.0.2.4, 7.0.2.3
最新が8.0.2であることがわかります
- railsの最新バージョン確認サイト
- Rubyの最新バージョン確認サイト
次にGemfile
を記述します
Gemfile
Rails やその他必要な Ruby ライブラリ(=gem)を記載するファイル
「何の gem が必要か」を定義し、bundle install コマンドで使います
source 'https://rubygems.org'
ruby "3.4.5"
gem 'rails', '~> 8.0.2'
-
source 'https://rubygems.org'
- gem(Rubyライブラリ)の取得元を指定します
-
https://rubygems.org
は公式のgem配布サイトです
-
ruby "3.4.5"
- このアプリが動作する Ruby のバージョンを指定します
- BundlerやRailsは、この記述を見て指定バージョンのRubyが必要ですと判断します
Gemfileの ruby と Dockerfileの FROM は 必ず一致させましょう
-
gem 'rails', '~> 8.0.2'
-
rails
という gem をインストール -
~> 8.0.2
はバージョン指定-
~>
は楽観的なバージョン指定 - 8.0.2 以上 かつ 8.1.0 未満のバージョンを許可する
-
-
Gemfile.lock
Gemfile を元に bundle install したときに、自動生成されるロックファイル。
docker-compose.yml
ファイルを記述します
docker-compose.yml
複数のコンテナの設定を1つにまとめて書けるファイルです。
実際のコンテナ(Rails用・DB用など)は別々に作られますが、このファイルを使えばまとめて起動・停止・管理ができるようになります。
version: '3'
services:
db:
image: postgres:12
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
-
共通設定
-
version: '3'
Composeファイルのバージョン。'3'は安定して使われる一般的なバージョンです -
services
:ここに記述した名前(例:web、db)がコンテナ名の識別子になります- 基本的に1サービスにつき1コンテナが推奨されています
-
-
データベースの設定
-
image: postgres:12
:dbのイメージにはpostgres:12を使います -
environment
:環境変数には、dbのユーザー名とパスワードを設定しますPOSTGRES_USER: postgres
POSTGRES_PASSWORD: password
-
-
Railsの設定
-
build: .
:Dockerfileが存在するカレントディレクトリを指定してビルドを行いDockerfileからイメージを作成します -
command
:その後、下記のコマンドを実行します -
bundle exec rails s -p 3000 -b '0.0.0.0'
-
bundle exec
- Bundler 経由でコマンドを実行する。
-
Gemfile.lock
に書かれたバージョンの gem を優先的に使うので、環境差異やバージョン違いによるエラーを防げる。
-
rails s
-
rails server
の短縮形。 - Rails アプリの開発用 Web サーバーを起動する
-
-
-p 3000
- ポート番号を指定
- ブラウザから
http://localhost:3000
でアクセスできるようにする
-
-b '0.0.0.0'
- バインドアドレスを指定:サーバーが起動時に「どのIPで待ち受けるか」を指定
-
0.0.0.0
は「すべてのネットワークインターフェースで待ち受ける」という意味 - Dockerや仮想環境でホストからアクセス可能にするために必要(デフォルトの
localhost
だと外から繋げない)
-
-
volumes
:ローカルのカレントディレクトリをコンテナ内の/myappディレクトリにマウントして、同期します
コンテナから中身が見えて編集もできますが、ソースコードはホスト側にあります -
ports:- "3000:3000"
:ホストとコンテナのポートを繋げてインターネットがコンテナ内まで届くようにします -
depends_on:db
:docker compose up
で起動した際のサービスの起動順の制御をします。dbと記述することでdbが起動してからweb:Railsが起動します
-
3. DB設定フェーズ:接続
detabase.yml
Railsアプリが、「どのデータベースに」「どうやってつなぐか」を指定するファイルです。このファイルは、環境ごと(development / test / production)にデータベースの接続情報を定義します。(docker-compose.ymlと一致させる)
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password: password
pool: 5
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
-
adapter: postgresql
使用するデータベースの種類を指定。今回は、PostgreSQLを指定します -
encoding: unicode
データベースの文字コードを設定します -
host: db
DBサーバーのホスト名を記述します。ここで指定している db は、docker-compose.yml におけるサービス名です
Dockerネットワーク上では、サービス名=ホスト名として解決されるため、db と書けばそのコンテナに接続できます -
username: postgres
PostgreSQLにログインするためのユーザー名です。docker-compose.yml の中で指定していれば、それと一致させる必要があります -
password: password
PostgreSQLのログインパスワード。
こちらも docker-compose.yml で環境変数として渡します -
pool: 5
DB接続の同時最大数 -
development: <<: *default database: myapp_development
<<: *default は「defaultセクションの設定をすべて読み込む」という意味-
database: myapp_development
は「開発用のDBの名前」を指定。
PostgreSQLコンテナ内に「myapp_development」という名前のDBが作成され、Railsがそれに接続する。
-
-
test: <<: *default database: myapp_test
テスト環境専用のDBを指定します
RSpecやMinitestなどでテストを実行すると、Railsは自動的にこの test 設定を使用し、myapp_test データベースに接続します
docker compose up
エラー発生
Missing secret_key_base for 'production' environment
本番環境のための秘密鍵がありません
-
docker-composefile.yml
内でRAILS_ENV
を指定しない場合、Railsはデフォルトでproduction
(本番モード)で起動するそうです。しかし、本番モードではsecret_key_base
の設定が必須だったため、未設定だと起動時にエラーになります
2つの解決方法
- ①
secret_key_base
が不要な開発モードかテストモードで起動する - ②
secret_key_base
を設定して本番モードで起動する
今回は、①の解決方法で解決します
docker-compose.yml
のweb
サービスに以下を追加:
services:
web:
environment: #追加
- RAILS_ENV=development #development(開発)追加
一応解決方法②も書いておきます
本番モードのままsecret_key_base
を設定します
docker-compose.yml
のweb
サービスに以下を追加:
services:
web:
environment: #追加
- RAILS_ENV=production #production(本番)追加
- SECRET_KEY_BASE=あなたのキー文字列 #追加
今回は、開発モードで起動するために環境変数RAILS_ENV
にdevelopment
を設定しました
version: '3'
services:
db:
image: postgres:12
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
environment: #追加
RAILS_ENV: development #追加
docker compose up
Railsのコンテナ内にデータベースを作成します
docker compose exec web rails db:create
エラー発生
LoadError: cannot load such file -- bootsnap/setup
bootsnap/setup
というファイルを読み込めない
Gemfile
にgem 'bootsnap'
を追加
gem 'bootsnap'
しかし、gemfileにこれだけを書くと
Rails(boot.rb)の中にすでに下記のコードがあるため二重ロードになったり、タイミングがバラけてエラーになることがあります
require "bootsnap/setup"
これはアプリケーション起動時に手動で bootsnap を読み込む設定です
それに対して、Gemfile にこう書くと…
gem 'bootsnap'
Bundler(gemの管理システム)が自動的にアプリ起動時に require 'bootsnap'
しようとします。
しかし、すでにboot.rb
でrequire
しているので、「この gem
は読み込まないで(requireしないで)」と指示することでboot.rb
の手動読み込みだけが有効になり、エラー回避に繋がるそうです。
Gemfile
:Gemを使う宣言 → Gemをインストールできるようにする
boot.rb
:Gemを実際に使う(読み込む)処理
require: false
:手動で読み込むなら、自動読み込みはオフにしておく
Gemfileにgem 'bootsnap', require: false
を追加:
code Gemfile
ruby '3.4.5'
gem 'rails', '~> 8.0.2'
gem 'bootsnap', require: false #追加
Gemfileを編集したので再ビルドして起動します。再ビルドして起動は下記のコマンドで一括でできるので今後はこちらのコマンドを使っていきます。
docker compose build
docker compose up
↓短縮系
docker compose up --build
docker compose exec web rails db:create
エラー発生
NoMethodError: undefined method `assets' for an instance of Rails::Application::Configuration
NoMethodError: Rails::Application::Configurationのインスタンスにはassetsというメソッドは定義されていません
これはRails7以前の設定ファイルにだけ存在していたconfig.assets
という設定がRails8では削除されたために起きるエラーです
Rails 8.0からはsprocketsを標準で使わない(=config.assetsは使えない)そうです。そのため、Rails 8ではconfig.assets
自体が削除されています
そのためconfig.assets
を削除します
削除する場所を探します
config
内のconfig.assets
と書かれている項目をすべて抽出します
grep -rn "config.assets" config/
オプションの意味
-
-r
再帰的にサブフォルダも検索(config/配下すべて) -
-n
該当行の行番号を表示 -
"config.assets"
この文字列を含む行を探す
config/environments/production.rb:28:config.assets.css_compressor = :sass
config/environments/production.rb:31:config.assets.compile = false
config/environments/development.rb:60:config.assets.quiet = true
config/initializers/assets.rb:4:Rails.application.config.assets.version = "1.0"
config/initializers/assets.rb:7:Rails.application.config.assets.paths << Emoji.images_path
config/initializers/assets.rb:12:Rails.application.config.assets.precompile += %w( admin.js admin.css )
それぞれのファイルを開いて上記の項目をコメントアウトします
code config/environments/production.rb config/environments/development.rb config/initializers/assets.rb
# config.assets.css_compressor = :sass
# config.assets.compile = false
# config.assets.quiet = true
# Rails.application.config.assets.version = "1.0"
# Rails.application.config.assets.paths << Emoji.images_path
# Rails.application.config.assets.precompile += %w( admin.js admin.css )
docker compose exec web rails db:create
エラー発生
NoMethodError: undefined method `assets' for an instance of Rails::Application::Configuration
また同じエラーでた、、、、、
反映させるために起動中のコンテナ群とネットワーク・ボリュームをまとめて停止&削除します
docker compose down
続けて、tmp/
ディレクトリを削除します
tmp/
は、Railsがキャッシュやセッション、一時ファイルなどを保存している場所です
Railsが古いキャッシュを使ってバグることがあるので、削除してクリーンな状態にします
rm -rf tmp/*
Dockerイメージをキャッシュを使わずに完全に作り直します
docker compose build --no-cache
docker compose up
docker compose exec web rails db:create
成功!!!!!!
docker compose up
エラー発生
LoadError: Error loading the 'postgresql' Active Record adapter.
pg is not part of the bundle. Add it to your Gemfile. (LoadError)
また別のエラーでた、、、、
postgresql の Active Record アダプタを読み込む際にエラーが発生しました。
pg は bundle(インストールされたgem群)に含まれていません。
Gemfile に pg を追加してください。
Gemfileに追加:
ruby '3.4.5'
gem 'rails', '~> 8.0.2'
gem 'pg', '~> 1.4' #追加
gem 'bootsnap', require: false
Gemfileを修正したので再度ビルドを実施します
docker compose up --build
エラー発生
LoadError: Error loading the 'postgresql' Active Record adapter.
Missing a gem it depends on? pg is not part of the bundle.
Add it to your Gemfile. (LoadError)
また同じエラーでた、、、
Gemfileには記載しているので、変更を反映させるために下記の手順を実施します
コンテナ完全停止+削除します
docker compose down --volumes --remove-orphans
Gemfile変更を反映させるためにイメージをビルドし直します
docker compose up --build
エラー発生
Could not find a server gem. Maybe you need to add one to the Gemfile?
gem "puma"
server 用の gem が見つかりません。Gemfile にgem "puma"を追加する必要があるかもしれません。
source 'https://rubygems.org'
ruby '3.4.5'
gem 'rails', '~> 8.0.2'
gem 'pg', '~> 1.4'
gem 'puma', '~> 6.0' #追加
gem 'bootsnap', require: false
Gemfile変更を反映させるためにイメージをビルドし直します
docker compose up --build
成功!!!!!!
ブラウザにてlocalhost:3000で検索します
エラー発生
migrateできていません。
docker compose exec web rails db:migrate
マイグレーションファイルに従ってテーブルなどを構築します
ブラウザにてlocalhost:3000で検索して確認をします
エラー発生
未定義のローカル変数またはメソッド javascript_importmap_tags が、このオブジェクトには存在しません。
importmap-rails gem
がGemfile
にない場合に起こるそうです
Gemfile に以下を追加:
source 'https://rubygems.org'
ruby '3.4.5'
gem 'rails', '~> 8.0.2'
gem 'pg', '~> 1.4'
gem 'puma', '~> 6.0'
gem 'importmap-rails' #追加
gem 'bootsnap', require: false
docker compose build
Importmap
をコンテナ内にインストールします
docker compose run web rails importmap:install
docker compose up
無事にブラウザに表示することができました!!!
最終構成 & 手順まとめ
- DockerとDocker Composeのインストール確認
- RailsアプリをGitHubからクローン
- 必要なファイルを作成
- Dockerfile の編集
- Gemfile の編集
- config/database.yml の修正
- コンテナをビルド&起動
- DB作成とマイグレーション
- Importmap をインストールする
- ブラウザでアプリ起動を確認
1. DockerとDocker Composeのインストール確認
docker -v
docker compose version
2. RailsアプリをGitHubからクローン
git clone https://github.com/<githubユーザー名>/<対象リンク> rails_docker
cd rails_docker
git checkout -b docker
3. 必要なファイルを作成
touch Dockerfile Gemfile Gemfile.lock docker-compose.yml
4.Dockerfile の編集
FROM ruby:3.4.5
RUN apt-get update -qq && apt-get install -y \
nodejs \
postgresql-client \
yarn
WORKDIR /rails_docker
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
5.Gemfile の編集
source 'https://rubygems.org'
ruby '3.4.5'
gem 'rails', '~> 8.0.2'
gem 'pg', '~> 1.4'
gem 'puma', '~> 6.0'
gem 'importmap-rails'
gem 'bootsnap', require: false
Gemfile.lock は空ファイルでOK。
6.Docker-compose.ymal の編集
version: '3'
services:
db:
image: postgres:12
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
environment:
RAILS_ENV: development
7.config/database.yml の修正
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password: password
pool: 5
development:
<<: *default
database: myapp_development
test:
<<: *default
database: myapp_test
8. コンテナをビルド&起動
docker compose up --build
9.config.assets設定を削除
grep -rn "config.assets" config/
config/environments/production.rb:28:config.assets.css_compressor = :sass
config/environments/production.rb:31:config.assets.compile = false
config/environments/development.rb:60:config.assets.quiet = true
config/initializers/assets.rb:4:Rails.application.config.assets.version = "1.0"
config/initializers/assets.rb:7:Rails.application.config.assets.paths << Emoji.images_path
config/initializers/assets.rb:12:Rails.application.config.assets.precompile += %w( admin.js admin.css )
それぞれのファイルを開いて上記の項目をコメントアウト
code config/environments/production.rb config/environments/development.rb config/initializers/assets.rb
# config.assets.css_compressor = :sass
# config.assets.compile = false
# config.assets.quiet = true
# Rails.application.config.assets.version = "1.0"
# Rails.application.config.assets.paths << Emoji.images_path
# Rails.application.config.assets.precompile += %w( admin.js admin.css )
10.DB作成とマイグレーション
docker compose exec web rails db:create
docker compose exec web rails db:migrate
11.Importmap をインストールする
docker compose exec web rails importmap:install
12. ブラウザでアプリ起動を確認
http://localhost:3000 にアクセスして、Railsアプリが起動していれば成功。
参考文献