はじめに
Railsで開発したアプリをDockerで動かしたいとき、Dockerとdocker composeを使うことで環境構築をコードとして管理できるようになります。
Docker化の手順を順に追って、つまずいたポイントと合わせてまとめました。
開発環境
- Ruby 3.2.2
- Rails 7.x
- PostgreSQL 12
- Docker / docker compose v2(スペース形式)
1. GitHub上のリポジトリをローカル環境へクローン
今回はDocker化がメインのテーマなので既存のRailsアプリを使用します。
Github上で使いたいプロジェクトのリポジトリページを開き、 Use this template
→ Create a new repository
を選択し、Repository name*
にリポジトリ名を入力してCreate repository
します。
ターミナルを開いて下記のコマンドを打って、Githubからローカルへプロジェクトを引っ張ってきて、フォルダの中に移動します。
今回はリポジトリ名をrails-docker
としています。
git clone https://github.com/YOUR-USERNAME/rails-docker
cd rails-docker
今回はこのクローンしたrails-docker
ディレクトリの中で、Docker化の作業を進めていきます。
できればgit checkout -b docker
でdocker
ブランチに作業ブランチを変更しておきましょう。(※そのまま main
で作業しても問題ありません)
2. Dockerfileの作成
Dockerfileとは、Dockerコンテナを作るための設計図です。
プログラムやサーバー環境(RubyやRailsなど)を「この順番で入れて、このコマンドを実行して、、」という手順をテキストで記述します。
ターミナルでひとつひとつコマンドを打つより時間もかからず、再現性が高いです。
ではやっていきます。
ターミナル上でrails-docker
内にいることを確認して、code Dockerfile
と打ちエディタで Dockerfileを開きます。(VSCode使用の場合。)
エディタで下記のように入力します。
FROM ruby:3.2.2
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
WORKDIR /rails-docker
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
CMD ["bin/rails", "server", "-b", "0.0.0.0"]
-
FROM
… Rubyのバージョンを指定します。Gemfile(後述)の中で指定するRailsと互換性のあるバージョンを指定します。 -
RUN
…apt-get update
でパッケージリストを更新し、apt-get install
でRailsアプリの実行に必要なライブラリをインストールします。-qq
は出力されるログを最小限に、-y
は全部Yesで進めるオプションです。 -
WORKDIR
… コンテナ内の作業ディレクトリ。色々な人がこのDockerファイルを使用して環境構築することが想定されるので、絶対パスで指定します。 -
COPY
… 現在のディレクトリ内容をコンテナへコピー。最初にGemfileとGemfile.lockのみコピーすることでキャッシュを活用できるようにします。 -
CMD
… コンテナ起動時のデフォルト実行コマンド。後でdocker-compose.ymlで上書きされますが、記述しておいた方がDockerfile単独でも起動できるので安全です。
3. docker-compose.ymlの作成
docker-compose.ymlは、複数のDockerコンテナ(Rails + DBなど)を一括で管理して起動するための設定ファイルです。
たとえば、RailsアプリとPostgreSQLを一緒に動かす場合に、どのイメージを使って、どのポートで公開して、どんな環境変数を渡すか、などを定義できます。
rails-docker
直下に docker-compose.yml
ファイルを作成し、下記のように記述します。
services:
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/rails-docker
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
tty: true
stdin_open: true
ports:
- "3000:3000"
depends_on:
- db
db:
image: postgres:12
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=myapp_development
ports:
- "5432:5432"
-
services:
… 起動する各コンテナを定義します。ここではweb
(Rails)とdb
(PostgreSQL)の2つで構成されています。 -
web.build
…Dockerfile
があるディレクトリからイメージをビルドします。.
は「現在のディレクトリ」を意味します。 -
web.command
… コンテナ起動時に実行されるコマンドを指定します。ここでは Rails を3000番ポート(Railsのデフォルトポート)で起動します。 -
web.volumes
… ローカルのソースコードをコンテナ内にマウントします。ローカル上に置いてあるコードの開発中の変更をコンテナに即時反映できます。 -
web.environment
… 環境変数の設定を行います。Railsのdatabase.yml
などで読み込まれます。 -
web.tty
…rails console
などを対話的に使いたいときに必要です。 -
web.stdin_open
…標準入力(STDIN)を開いたままにします。ユーザー入力を受け付けることができるようになります。 -
web.ports
…ホスト
:コンテナ
の順で指定して、ホストのポートとコンテナのポートをつなげます。この場合`ローカルの http://localhost:3000 にアクセスすると、Railsアプリ(コンテナ内の3000番)できるようになります。 -
web.depends_on
…db
コンテナが先に起動されるように順序を制御します。 -
db.image
… PostgreSQLの公式イメージを使用します。postgres:12
のようにバージョンの指定もできます。 -
db.environment
… ユーザー、パスワード、DB名などのデータベースの初期設定ができます。これらはRailsのconfig/database.yml
の記述と揃える必要があります。 -
db.ports
… DBに外部からアクセスできるようにするためのポート設定です。
4. database.ymlの作成
database.yml
は、Railsアプリとデータベースをつなぐための設定ファイルです。rails db:create
や rails db:migrate
はこのファイルの内容に従って処理されます。
rails-docker/config
直下にdatabase.yml
ファイルを作成し、下記のように記述します。
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password: postgres
pool:
development:
: *default
database: myapp_development
test:
: *default
database: myapp_test
username: myapp
password:
-
adapter:
… 使用するデータベースの種類です。 -
encoding:
… データベースの文字コードを設定します。通常はunicode
を指定します。 -
host:
… データベースサーバーのホスト名です。docker-compose.yml
で定義した DB サービス名(ここではdb
)と一致させる必要があります。これが異なると、RailsからDBに接続できずエラーになります。 -
username:
… 接続時に使用するユーザー名です。 -
password:
… 上記ユーザーに対応するパスワードです。セキュリティを考慮して別途.env
ファイルを作って管理することもあります。今回は直接記載しています。 -
pool:
… データベースへの同時接続数の上限です。スレッド数に応じて調整します。 -
database:
… 作成されるデータベース名です。開発環境・テスト環境・本番環境でそれぞれ異なる名前を指定します。
5. Gemfileの作成とGemfile.lock
Gemfile
は、Railsアプリで使用するRubyのライブラリ(gem)の依存関係をまとめて管理するためのファイルです。
このファイルを使うことで、アプリケーションに必要な機能をgemという形で追加し、それらをチーム全体で共有できるようになります。Gemfile
を変更するとDockerのビルドキャッシュが無効になるため、docker compose up --build
を実行し直す必要があります。
Gemfile.lock
は、Gemfile
に書かれた依存関係をもとに 実際にインストールされたgemのバージョンを記録するファイルです。
チーム開発で gem のバージョンを揃えるために重要で、bundle install
を実行することで自動生成・更新されます。
rails-docker
直下に Gemfile
ファイルを作成し、下記のように記述します。
source "https://rubygems.org"
ruby "3.2.2"
gem "rails", "~> 7.x"
gem "pg", "~> 1.1"
# 他にも使用したいgemをここに追加していきます
-
source:
…使用するGemの取得元(リポジトリ)を指定します。 -
ruby:
…使用するRubyのバージョンを指定します。Dockerfileにも同じバージョンを指定しておくと整合性が取れます。 -
gem:
… 利用するライブラリ(gem)の名前とバージョンを指定します。~>
を使うことで柔軟なバージョン指定ができます。
6. .dockerignoreファイルの作成
.dockerignore
に記載することで、Dockerイメージを作成する際に含めたくないファイルを除外します。現在作成していないファイルやフォルダでも、とりあえず含めておくと後から作った時に安心です。
rails-docker
直下に.gitignore
ファイルを作成し、下記のように記述します。
log/*
tmp/*
*.log
*.swp
.DS_Store
node_modules
7. コンテナの起動とDB設定
必要なファイルが作成できたのでターミナルに戻り、下記コマンドを打ってコンテナを起動します。--build
はDockerイメージを再ビルドしてからコンテナを起動するオプションです。DockerfileやGemfile に変更を加えたあとなど、ビルド内容を更新したいときに使用します。
docker compose up --build
その後、下記コマンドでデータベースの作成とマイグレーションをします。
docker compose exec web rails db:create
docker compose exec web rails db:migrate
docker compose exec
は、すでに起動しているコンテナの中でコマンドを実行するためのコマンドです。
このとき、どのサービス(コンテナ)に入るかを指定するために、web を付けています。
rails db:create
はdatabase.yml
に基づいて、指定されたデータベースを作成します。rails db:migrate
はdb/migrate/にあるマイグレーションファイル(設計図)に書かれた内容にしたがって、データベースの構造(テーブルやカラム)を作成・更新します。
「どんなカラムが必要か」「どんな制約があるか」など、アプリで使うデータの形がここで決まります
これでhttp://localhost:3000 にアクセスすると、Railsアプリの起動が確認できるでしょう。
もしhttps://localhost:3000 にリダイレクトされてしまって表示がうまくいかない場合は、ブラウザのキャッシュや履歴を削除してから再読み込みしてみてください。
8. GitHubにpush
http://localhost:3000 に接続してRailsアプリの起動が確認できたら、GitHub上にpushしてローカルとリモートの状態を同期させておきます。
作業ブランチを分けていない人はgit push origin main
または git push origin master
でpushします。
git add .
git commit -m "コミットメッセージ"
git push origin docker
また、GitHub ActionsなどのCI環境では docker-compose
が使えないので docker compose
の方を使います。テストが通らない時は確認してみてください。
ちなみに、大文字と小文字を間違えてDocker-compose.yml
などとタイポするとローカルでは動くがGiuhub上のテストが通らないなんてことが起こるので注意してください。
ファイル名の変更をしてもローカル上で同じと認識されて普通にはcommitが通らないので少しめんどくさいことになります。
参考にしたページ
公式ドキュメント(日本語訳)を参考にしました。
ぜひハンズオンで学んでみてください。
おわりに
Docker化につまずいた人の参考になれば幸いです!
Views: 0