このページで解説している内容は、以下の YouTube 動画の解説で見ることができます。

Docker超入門:開発環境コンテナ:Ruby on Rails②

🐳 開発環境コンテナ:Ruby on Rails②

前回の「Ruby on Railsコンテナ①」でDockerfileを定義し、Rails環境を準備しましたね。
 今回はその続きとして、compose.yamlファイルの作成Railsプロジェクトの生成を行っていきます。
構築する「開発環境コンテナ:Ruby on Rails」は下図のとおりです。

ここでは、Railsアプリケーションが実際にMariaDBと連携できる状態まで整っていきます。

「開発環境コンテナ:Ruby on Rails」は3部構成で進めています。

⚙️ compose.yamlファイルの作成

まずはDocker Composeを使って、複数のコンテナをまとめて管理できるようにします。

VSCodeでファイルを作成します👇

code compose.yaml

VSCodeが開いたら、以下の内容を入力して保存しましょう。

services:
  db:
    image: mariadb:10.7
    container_name: mariadb_container
    environment:
      MARIADB_ROOT_PASSWORD: testpass
      MARIADB_DATABASE: samplerails_development
    volumes:
      - db-data:/var/lib/mysql
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -ptestpass --silent"]
      interval: 5s
      timeout: 3s
      retries: 20
      start_period: 60s

  web:
    build: .
    container_name: rails_container
    depends_on:
      db:
        condition: service_healthy
    environment:
      RAILS_ENV: development
      DATABASE_HOST: db
      DATABASE_PORT: 3306
      DATABASE_USER: root
      DATABASE_PASSWORD: testpass
    ports:
      - "3000:3000"
    volumes:
      - .:/samplerails
    command: >
      bash -c "
        echo 'Waiting for MariaDB to be ready...' &&
        until mysqladmin ping -h db -u root -ptestpass --silent; do
          sleep 2;
        done &&
        echo 'MariaDB is ready. Running db:prepare...' &&
        bundle exec rails db:prepare &&
        bundle exec rails s -b 0.0.0.0"
volumes:
  db-data:

🧱 定義内容の解説

 このcompose.yamlでは、MariaDBコンテナ(db)とRailsコンテナ(web)の2つのサービスを定義しています。

サービス名役割主な設定
dbデータベース用(MariaDB)mariadb:10.7 イメージを使用し、rootパスワードや初期DB名を設定。db-dataボリュームでデータを永続化。
webRailsアプリケーションカレントディレクトリのDockerfileを使ってビルド。MariaDBが起動完了してからRailsを起動。ポート3000を公開。

💡 ポイント

  • depends_ondbの起動完了(ヘルスチェック成功)を待ってからRailsを起動するよう制御しています。
  • volumesを使って、ホストのソースコードをコンテナ内に反映します。
  • commandでMariaDBの起動確認を自動化しており、DBが準備できるまで待機してからRailsを起動します。

🩺 healthcheckの動作解説

MariaDBの準備完了を確認するために、healthcheckセクションを使っています。

healthcheck:
  test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -ptestpass --silent"]
  interval: 5s
  timeout: 3s
  retries: 20
  start_period: 60s
項目意味
testコンテナのヘルスチェック内容を定義。mysqladminコマンドでMariaDBの応答を確認します。
intervalチェックを実行する間隔。ここでは5秒ごとに実行。
timeout各チェックのタイムアウト時間。3秒以内に応答がない場合は失敗扱い。
retries失敗を何回まで許容するか。ここでは最大20回までリトライ。
start_periodコンテナ起動後、ヘルスチェックを始めるまでの待機時間。MariaDBの初期化時間を考慮して60秒に設定。

💡 ポイント

 healthcheckを設定しておくことで、MariaDBの起動が完全に終わる前にRailsが接続を試みてエラーになる問題を防げます。

test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -ptestpass --silent"] の解説

この行は Docker Composeの healthcheck 機能 の一部で、
 MariaDB コンテナ(DBコンテナ)が「起動して正常に動作しているか?」を自動で確認するための テストコマンド を指定しています。

では、1つずつ丁寧に分解して解説します👇

🩺 コマンド全体の役割

test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -ptestpass --silent"]

これは、Docker Composeの healthcheck セクション内で使われる定義です。
目的はシンプルで、

MariaDBコンテナが「応答できる状態」かどうかを定期的に確認する

というものです。
もし正常に動いていれば「Healthy(正常)」、
応答できなければ「Unhealthy(異常)」という状態をDockerが判断します。

🧩 各要素の意味

要素意味補足説明
test:コンテナのヘルスチェックで実行するコマンドを指定CMDまたはCMD-SHELL形式で指定できます。
"CMD-SHELL"シェル経由でコマンドを実行するモード/bin/sh -c の形で実行されます。パイプや変数展開などシェル構文が使えます。
"mysqladmin ping -h localhost -u root -ptestpass --silent"MariaDBサーバーへの接続確認コマンドMariaDBにpingを送り、「サーバーが生きているか?」を確認します。

🧠 実際の動作の流れ

  1. Docker は MariaDB コンテナを起動したあと、healthchecktest コマンドを定期的に実行します。
  2. 内部的には次のように動きます👇
    /bin/sh -c "mysqladmin ping -h localhost -u root -ptestpass --silent"
  3. mysqladmin ping コマンドが「サーバーが起動して応答可能」なら成功(exit code 0)になります。
  4. 成功(0)であればコンテナは「healthy」とマークされ、
    失敗(非0)なら「unhealthy」とマークされます。

🧱 mysqladmin ping の動作

ここで使われている mysqladmin ping は、
MySQL / MariaDB が起動し、クライアントの接続を受け付けられる状態かを確認するサブコマンドです。

mysqladmin ping -h localhost -u root -ptestpass --silent
部分意味
mysqladminMariaDBの管理コマンドツール
pingサーバー応答確認を行うサブコマンド
-h localhostMariaDBのホスト名(同一コンテナ内のためlocalhost
-u rootrootユーザーとして接続
-ptestpassパスワードを直接指定(※セキュリティ的には.env利用が推奨)
--silent出力を抑制(成功・失敗を終了コードで判断)

「-p testpass」ではなく「-ptestpass」なのか

実はこれ、MySQL系コマンド(mysql・mysqladminなど)の特殊な仕様なんです。
見た目がちょっと不自然に見えるけど、正しい書き方なんですよ。

では詳しく説明していきましょう👇

💡 結論から言うと

-pTESTPASS   ✅ 正しい書き方
-p TESTPASS  ❌ 間違い(もしくは無視される)

MySQLのコマンドでは、
-pオプションのあとに「スペースを入れずに」パスワードを書く
というルールになっています。

🧩 理由:MySQLクライアントのオプション解析の仕組み

MySQL(およびMariaDB)のコマンドは、-pを見たときにこう動作します👇

書き方挙動
-ptestpassパスワード「testpass」を使ってログイン
-p(単独)パスワード入力を対話的に求める(プロンプトが出る)
-p testpasstestpassを「接続先ホスト名」として解釈してしまう(エラーの原因)

つまり、スペースを入れると「次の引数は別の意味」だと認識されてしまうんです。

🧠 command の動作解説

 Railsコンテナの中でどんな順序で処理を実行するかを指定しているのが、このcommandセクションです。
RailsとMariaDBを確実に連携させるための仕掛けになっています👇

command: >
  bash -c "
    echo 'Waiting for MariaDB to be ready...' &&
    until mysqladmin ping -h db -u root -ptestpass --silent; do
      sleep 2;
    done &&
    echo 'MariaDB is ready. Running db:prepare...' &&
    bundle exec rails db:prepare &&
    bundle exec rails s -b 0.0.0.0"

このスクリプトの流れを説明します👇

処理内容説明
echo 'Waiting for MariaDB to be ready...'MariaDBの起動を待機することをユーザーに知らせるメッセージ。
until mysqladmin ping -h db -u root -ptestpass --silent; do sleep 2; doneMariaDBコンテナ(サービス名:db)にpingを送って接続確認。応答があるまで2秒ごとに再試行します。
echo 'MariaDB is ready. Running db:prepare...'MariaDBが使える状態になったら、Rails側のDB準備を開始します。
bundle exec rails db:prepareRailsアプリで使用するデータベースを作成・マイグレーションして準備します。
bundle exec rails s -b 0.0.0.0Railsアプリを起動し、外部アクセス(ポート3000)を受け付けられるようにします。

💡 この設定のねらい

通常、MariaDBの起動には少し時間がかかるため、Railsがすぐに起動すると「DB接続できません」エラーが出がちです。
このcommand:定義により、Railsが自動的にMariaDBの準備完了を待ってから起動するため、安定した立ち上げが可能になります。

mysqladmin ping -h db -u root -ptestpass の解説

このコマンドは MariaDB(またはMySQL)サーバーに接続できるかを確認するためのコマンド です。
つまり、「DBがちゃんと起動して、接続を受け付けられる状態になっているか?」をチェックします。

では、1つずつ分解して説明します👇

🧩 コマンド全体

mysqladmin ping -h db -u root -ptestpass

このコマンドは、mysqladmin というMySQL/MariaDB管理ツールを使って、
ホスト(ここでは db)上のデータベースサーバーが応答できるかを「ping」するものです。

🧱 各部分の意味

部分意味補足
mysqladminMySQL / MariaDB の管理用コマンドツールサーバーの状態確認、ユーザー管理、データベース作成なども可能。
pingDBサーバーに接続して応答確認を行うサブコマンドサーバーが起動していれば「mysqld is alive」と返します。
-h db接続先ホストを指定(ここでは db サービス)Docker Compose内ではサービス名がホスト名として解決される。つまり「mariadb_container」ではなく「db」でアクセス可能。
-u root接続するユーザー名MariaDBのrootユーザーとして接続。
-ptestpass接続パスワードを指定パスワードを直接指定(※セキュリティ的には.env利用が推奨)

💬 実行時の動作

このコマンドを実行すると、MariaDBサーバーに対して以下のようなやりとりが行われます👇

  1. db ホスト(=MariaDBコンテナ)に TCP 接続を試みる。
  2. ユーザー root とパスワード testpass を使ってログインを試みる。
  3. サーバーが応答可能であれば、次のようなメッセージを返します。
    mysqld is alive
  1. もしサーバーがまだ起動途中なら、エラーが返ります。
    mysqladmin: connect to server at 'db' failed

healthcheck と command の両方必要?

 この「healthcheck」と「command内のMariaDB待機処理」は、どちらも“DBが起動するまで待つ”という目的は同じですが、
役割と実行タイミングが違うため、併用するとより安全に動作します。
ただし、構成によってはどちらか一方だけでも動作します。
順に詳しく説明します👇

🩺 ① healthcheck の役割

healthcheckは、MariaDBコンテナの“内部状態”を監視する仕組みです。
Composeに次のように書かれていますね。

healthcheck:
  test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -ptestpass --silent"]
  interval: 5s
  timeout: 3s
  retries: 20
  start_period: 60s

この定義により、MariaDBコンテナ内で5秒ごとにmysqladmin pingを実行し、
「DBが応答できる状態になったか?」をチェックします。

健康状態(Healthy/Unhealthy)はComposeの内部で管理され、
depends_on: condition: service_healthy で他のコンテナに伝わります。

💡 つまり…

  • healthcheck は MariaDBの中で動く監視(Dockerエンジンが評価)
  • Railsコンテナは 「dbがhealthyになったら起動してOK」 という判定をもらってからスタート

ポイント
これで「MariaDBがまだ初期化中なのにRailsが先に起動して接続失敗」という事態をかなり防止できます

🧠 ② command内の待機処理の役割

次に、Rails側のcommand:の中でやっているこの部分です👇

command: >
  bash -c "
    echo 'Waiting for MariaDB to be ready...' &&
    until mysqladmin ping -h db -u root -ptestpass --silent; do
      sleep 2;
    done &&
    echo 'MariaDB is ready. Running db:prepare...' &&
    bundle exec rails db:prepare &&
    bundle exec rails s -b 0.0.0.0"

このスクリプトは、Railsコンテナの中で実際にMariaDBへ接続を試みて待機する処理です。
つまり、healthcheckよりもさらに実戦的な接続確認です。

Rails側では次の順に動きます👇

ステップ処理内容
MariaDBコンテナ(サービス名db)にpingを送り、応答があるまで2秒ごとに再試行
接続成功後にrails db:prepareでDBを初期化/マイグレーション
その後にrails sでWebサーバー起動

ポイント
healthcheckが「MariaDBが動作可能か」を判断するのに対して、
command内では「Railsが実際にMariaDBへ接続できるか」をチェックしています。

⚖️ 両方とも必要なの?

結論をまとめると以下の通りです👇

組み合わせメリット注意点
両方使う(推奨)healthcheckで起動順を制御し、commandで実際の接続確認を行う。起動トラブルが最も少ない。やや冗長だが安定性が高い。
healthcheckのみMariaDBの起動状態までは保証される。Railsが起動直後に接続を試みた際に、MariaDBが応答準備中だと失敗する場合あり。
commandのみ簡潔で確実に接続確認できる。MariaDBコンテナがまだ起動していない場合、無駄に待機することがある。

💡 実運用では“両方併用”がベスト

🛠️ Railsプロジェクトの作成

続いて、Railsアプリケーション本体を作成します。

コマンドはこちら👇

docker compose run --rm web rails new . --force --no-deps --database=mysql

 このコマンドは、Docker Composeを使って一時的なRailsコンテナを起動し、プロジェクトを自動生成します。

項目説明
docker compose run指定したサービス(web)を一時的に起動してコマンドを実行。
--rmコマンド実行後、コンテナを自動削除。クリーンに実行可能。
web実行対象のサービス(Railsコンテナ)。
rails new .カレントディレクトリにRailsプロジェクトを新規作成。
--force既に存在するファイルを上書き。
--no-deps依存する他のサービス(dbなど)を起動せずに実行。
--database=mysqlデータベースとしてMySQL(MariaDB互換)を使用するよう設定。

💡 ポイント

このコマンドを使うと、Railsの基本構成ファイル(Gemfileやconfigフォルダなど)が自動で作成されます。

🖥️ 実行結果

実行には少々時間がかかります。

PS C:\Users\joeac\Desktop\docker\rails> docker compose run --rm web rails new . --force --no-deps --database=mysql
time="2025-10-20T01:43:53+09:00" level=warning msg="The \"DATABASE_PASSWORD\" variable is not set. Defaulting to a blank string."
[+] Running 9/9
 ✔ db Pulled                                                                                               10.2s
   ✔ d3da17671559 Pull complete                                                                             0.7s
(省略)
Bundle complete! 14 Gemfile dependencies, 87 gems now installed.
(省略)

 完了メッセージに「Bundle complete! 14 Gemfile dependencies, 87 gems now installed.」と表示されれば成功です。
これでRailsプロジェクトの雛形が生成されました。

⛔ 一時コンテナの停止

Railsプロジェクトを作成したコンテナは一時的なものなので、作業後に停止します。

docker compose stop
コマンド説明
docker compose stop起動中のコンテナを停止します。イメージやデータは保持されます。

実行結果👇

PS C:\Users\joeac\Desktop\docker\rails> docker compose stop
[+] Stopping 1/1
 ✔ Container mariadb_container  Stopped                                                                     1.6s
PS C:\Users\joeac\Desktop\docker\rails>

🗂️ Railsプロジェクトの確認

VSCodeのエクスプローラでrailsフォルダを開くと、次のような構成になっています。

これでRailsプロジェクトの基盤が整いました!

 この続きでは「開発環境コンテナ:Ruby on Rails③」で、database.ymlの設定変更コンテナの起動・動作確認を行っていきます。

✅ まとめ

ステップ内容
compose.yamlを作成してMariaDBとRailsを連携設定
healthcheckでDB起動を確認してからRails起動
docker compose runでRailsプロジェクトを作成
docker compose stopで一時コンテナを停止

次はいよいよ Railsコンテナの起動とブラウザ表示の確認 に進みます。
ここまで来れば、あなたの開発環境はほぼ完成です! 🎉