Docker + Rails 開発環境をつくる
本を参考にしながらdockerでrailsを使おうとしたのですが、おそらくバージョンが古くなってしまっていたため、うまく開かなかったので、関係していそうな記事を読んでは試し、試行錯誤していました💭
↓
railsを導入できたときに参考にさせていただいた記事が、こちらになります。
なぜ成功できたのか、学習をかねてchatgptに聞きながら備忘録を残したいと思います。
【使用環境・バージョン】
・Mac
・Ruby 3.3
・Rails 7.1.3
・MySQL 8.3
【完成系】
「ディレクトリ構成」
|- service # Railsプロジェクトを格納するディレクトリ
|- db_data # MySQLのボリュームディレクトリ
|- compose.yml
|- Dockerfile
|- Gemfile # Railsのパッケージバージョンを記載
|- Gemfile.lock
「Dockerfile」
FROM ruby:3.3
WORKDIR /service #Dockefileの命令ひとつで、コンテナ内のカレントディレクトリを指定するもの。
これ以降の命令(COPY や RUN など)が このディレクトリを基準に実行される。
例えば、COPY Gemfile* ./ と書いた場合、./ は /service を指すようになります。
COPY Gemfile* /service/
RUN bundle install
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
#CMDとは
Dockerfile で コンテナ起動時に実行するコマンド を指定する。
例えば CMD ["echo", "hello"] と書くと、コンテナ起動時に echo hello が実行される。
Dockerfile に複数 CMD があっても最後の1つだけが使われる。
#"rails", "server"
これは rails server コマンドを実行するという意味。
Rails アプリを 開発用サーバー(Pumaなど)で起動する。
デフォルトではポート 3000 で待機する。
#-b "0.0.0.0"
-b は bind の略で、サーバーをどの IP にバインドするか指定する。
"0.0.0.0" は 全てのネットワークインターフェース に対して待ち受ける、という意味。
Docker コンテナではこれを指定しないと コンテナ内部でしかアクセスできず、ホスト(PC)からアクセスできない ことがある。
まとめ
CMD ["rails", "server", "-b", "0.0.0.0"]
「コンテナ起動時に Rails サーバーを起動し、コンテナの外(ホストPCやネットワーク)からもアクセスできるように待機せよ」という意味。
【ステップ1】
・Gemfileでは何をしているの?
「公式RubyGemsからRails 7.1系をインストールして使います」
source…ライブラリはこのリポジトリからダウンロードしてね
~> … 互換性のあるバージョンなら更新OK
・Dockerfileでは何をしているの?
1.Ruby 3.3 の環境を準備
2.作業ディレクトリを作る
3.必要なGemをコピーしてインストール
4.Railsサーバーを起動できる状態にする
3 COPY Gemfile* /service/
ホストPCの Gemfile と Gemfile.lock をコンテナ内の /service/ にコピー。
Rails プロジェクトの依存関係(どのGemを使うか)をコンテナに渡すため。
【dockerファイル→コンテナ起動の流れ】
ホストPC (自分のPC)
│
├─ Dockerfile (設計図)
│
└─ docker build → イメージ作成
│
▼
Docker イメージ
├─ Ruby 3.3
├─ 作業ディレクトリ /service
├─ Rails 必要なGem
└─ EXPOSE 3000
│
▼
docker run → コンテナ起動
│
▼
コンテナ内で
1. /service に移動 (WORKDIR)
2. Gemfile から Gem をインストール済み (bundle install)
3. Rails サーバー起動 (rails server -b 0.0.0.0)
│
▼
コンテナのポート3000を外部に公開
│
▼
ホストPCや他のネットワークから
http://localhost:3000 でアクセス可能
Dockerfile がコンテナの「設計図」となっている。
docker build で「設計図 → イメージ」
docker run / docker compose up で「イメージ → コンテナ」
コンテナ内で Rails サーバーが動き、外からアクセスできる
・compose.yml ではなにをしているの?
「build: .」
今いるディレクトリ(.)にある Dockerfile を使ってイメージを作る
=「このフォルダの Dockerfile を使って Web サービス用のコンテナを作れ」という意味
「ports: - '3000:3000'」
コンテナの 3000 番ポートを、ホストPCの 3000 番ポートに接続する
これで、ブラウザから http://localhost:3000 で Rails にアクセスできる
volumes(ボリューム)
- type: bind
source: ./service
target: /service
バインドマウント(bind mount)を指定している
意味:
ホストPCの ./service ディレクトリを
コンテナ内の /service ディレクトリに「そのまま見えるように」する
こうすることで:
ホストPCでコードを編集すると、コンテナ内にも即座に反映される
Rails の再ビルドや再起動なしで開発が可能
source はホスト側のフォルダ
target はコンテナ側のフォルダ
「ホストのフォルダをコンテナ内に繋げるイメージ」と覚えるとわかりやすい
・config/database.ymlはなぜ変更したの?
Rails と MySQL を Docker コンテナで連携させるための変更
元の設定(AS-IS)
username: root
password:
host: localhost
root ユーザーで接続
パスワードは空
ホストは localhost(自分のコンピュータ内の MySQL を指す)
⚠️ このままだと Docker コンテナ内の Rails からは MySQL に接続できません。
Docker では Rails と MySQL は別のコンテナで動く ため、localhost では「自分のコンテナ内の MySQL」を探してしまうからです。
変更後(TO-BE)
username: <%= ENV['MYSQL_USER'] %>
password: <%= ENV['MYSQL_PASSWORD'] %>
host: <%= ENV['MYSQL_HOST'] %>
ENV['MYSQL_USER'] や ENV['MYSQL_PASSWORD'] は Docker Compose の環境変数から読み込む
例: compose.yml で MYSQL_USER: myapp と設定
host はコンテナ名(例えば db)を指定
Docker Compose 内ではサービス名がそのままホスト名として使える
?ENVとは
ENV は 環境変数(Environment Variables) のこと
環境変数は OSやコンテナに設定された値をプログラムから参照する仕組み。
Rails では <%= ENV['変数名'] %> という形でアクセスする。
✅ こうすることで:
Rails コンテナは MySQL コンテナの場所(ホスト名 db)を自動で参照できる
ユーザー名・パスワードもコンテナ間で共通化できる
コードに直接パスワードを書かなくて済む(セキュリティ的に安全)
最後のエラーの意味は?
Rails が指定したデータベースに接続できない という意味
docker compose run web rails db:create
コマンドの意味
docker compose run web
…
docker compose:Docker Compose を使って複数のコンテナを管理するときに使うコマンド
run:指定したサービスのコンテナを 一時的に起動してコマンドを実行する
終了するとコンテナも基本的に停止する
web:docker-compose.yml の中で定義した web サービスを指定
💡 要は「web サービスのコンテナを作って、ここでコマンドを実行する」という意味。
rails db:create
…
Rails のコマンド
db:create:database.yml に書かれた開発用(development)やテスト用(test)の データベースを作成する
実際には MySQL や PostgreSQL 上にデータベースを作ります
全体の意味
「Docker Compose の web コンテナを起動して、Rails の db:create を実行し、MySQL コンテナ上にデータベースを作れ」という命令
Discussion