今回はRails環境をDockerで構築する方法についてです。
Docker Compose V1が非推奨となり、Docker Compose V2が推奨となることも踏まえてV2で行おうと思います。
Docker Desktopはインストール済み、アプリケーションを格納するフォルダは作成済みの状態で進めます。
Dockerfileの作成
まずはDockerfile
を作成します。
DockerfileはRailsの実行環境用のイメージを作成するためのファイルです。
次のコマンドでDockerfileを作成します。(今回はsamplev2というフォルダを作成したとします)
samplev2 % touch Dockerfile
そして、Dockerfileに以下の記述を追加します。
今回はRuby3.1.0を使用するため、冒頭にFROM ruby:3.1.0
を記載します。
FROM ruby:3.1.0 RUN apt-get update -qq && apt-get install -y postgresql-client WORKDIR /samplev2 COPY Gemfile/samplev2/Gemfile COPY Gemfile.lock/samplev2/Gemfile.lock RUN bundle install COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3000 CMD ["rails", "server", "-b", "0.0.0.0"]
少し記述について補足します。
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
はRailsアプリケーションに必要なNode.jsとPostgreSQLのインストールを行うように指定します。(PostgreSQLは必須ではありません)
WORKDIR /samplev2
は作業ディレクトリを指定します。ここに誤りがあるとうまくプロジェクトが作成されないので、注意が必要です。
COPY Gemfile/samplev2/Gemfile
はローカルのGemfileをsamplev2配下にコピーします。
COPY Gemfile.lock /samplev2/Gemfile.lock
はローカルのGemfile.lockをsamplev2配下にコピーします。
RUN bundle install
先程コピーしたGemfileに記載されているGemをbundle installするように指定します。
COPY entrypoint.sh /usr/bin/
はローカルのentrypoint.shを/usr/bin配下にコピーします。
RUN chmod +x /usr/bin/entrypoint.sh
でコピーしたentrypoint.shに権限を付与します。
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
でポート番号を指定して、Railsを実行します。
exec形式([""]
の形式)は指定したコマンドと引数がそのまま実行されるので、ENTRYPOINTやCMDはexec形式で記載しましょう。
Gemfileの作成
次にGemfile
を作成します。
今回はRails7.0.4.2のアプリケーションを使用するため、作成したGemfileには次のように、gem 'rails', '7.0.4.2'を記載します。
source 'https://rubygems.org' gem "rails", '7.0.4.2'
そして、Dockerfileをビルドするため、Gemfile.lock
も作成します。
Gemfile.lockは空の状態で作成します。
entrypoint.shの作成
次にentrypoint.sh
を作成します。
既にserver.pid
ファイルが存在してしまうことで、サーバーを再起動できない問題を解消するために追加します。
(server.pidはサーバー起動時に生成されます。生成されている場合、サーバーは起動状態にあると認識されます。
サーバー終了後、server.pidが残存する恐れがあり、サーバーを再起動する場合に「サーバーは起動しています」というエラーが発生する場合があります。
よって、明示的に残存したserver.pidを削除する事で問題なくサーバーを起動する事ができるようになります)
samplev2 % touch entrypoint.sh
で空のファイルを作成して、次のように設定します。
#!/bin/bash set -e # すでにserver.pidがある場合には削除 rm -f /samplev2/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@"
exec "$@"
でDockerfileのCMDで渡されたコマンド(→Railsのサーバー起動)を実行します。
compose.ymlの作成
次にアプリケーションを構成するサービス一覧を記載し、それらを一括で実行してくれるcompose.yml
を作成します。
V3からはcompose.ymlという名前が使えます。
以前使用していたdocker-compose.yml
は後方互換のためにしばらくサポートしているだけみたいなので、compose.ymlの方を使った方がいいと思います。
今回は、作成したcompose.ymlにdbとwebの2つを記載します。
dbはPostgreSQLを指定します。
samplev2 % touch compose.yml
で空のファイルを作成して、次のように設定します。
services: db: image: postgres volumes: - ./tmp/db:/var/lib/postgresql/data environment: POSTGRES_PASSWORD: password web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/samplev2 ports: - "3000:3000" depends_on: - db
services:
はservices配下にコンテナを定義します(今回はwebとdbのみ)。
image:
は利用するイメージの指定します(今回はPostgreSQL)。
volumes:
はデータを永続的に保存する場所を指定します(手元のデータをマウントしているなら、コンテナを立ち上げる度にデータが消えない)。
今回の場合は、手元でプロジェクトルートにファイルを作ると、コンテナ内の/sample2にも、ファイルが作られます。
environment:
はPostgreSQLに関する環境変数の設定(今回はパスワードを設定)
build: .
はDockerfileがあるディレクトリを指定しています。
depends_on:
はコンテナの実行順序の指定します(今回はDB起動からweb起動する設定にしています)
また、compose.yml内でversion: '3'のようにバージョンを記述する項目が非推奨になったので設定を入れていません。
Railsアプリケーションの作成
ここまでファイルを作成したら、Railsの新規アプリケーションを作成します。
samplev2 % docker compose run --no-deps web(ここはcompose.ymlで定義したサービス名) rails new . --force --database=postgresql
--force
を設定することで実行時にGemfileの上書きを行います。
--no-deps
を設定することでリンクされたコンテナを起動させないようにします。
--skip-bundle
を設定することでbundle installをスキップします(今回はgemを追加していないので)
ビルド
rails newで作成した新規アプリケーションのGemfileを更新するため、ビルドを実行します。
samplev2 % docker compose build
DBの作成
ビルドまで成功していれば、デフォルトのフォルダやファイルが作成されていると思います。 ここでDBを作成します。
まずはdatabase.yml
の編集を行います。
デフォルトではRailsはlocalhost上でDBが動作してしまうため、先ほど記述したDBコンテナを動作先に指定しましょう。
config/database.yml
のdefault部分を以下のように編集します。
// 編集前 default: &default adapter: postgresql encoding: unicode # For details on connection pooling, see Rails configuration guide # https://guides.rubyonrails.org/configuring.html#database-pooling pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> ↓ ↓ ↓ // 編集後 default: &default adapter: postgresql encoding: unicode host: db username: postgres password: password pool: 5
編集後は以下のコマンドでDBを起動します。
samplev2 % docker compose run web rails db:create
成功すると次のようにDBが作られると思います。
Created database 'samplev2_development' Created database 'samplev2_test'
アプリケーションの起動
ここまででDockerの設定を一通り終了しました。 最後にアプリケーションを立ち上げます。 Dockerを起動した状態で、次のコマンドを実行します。
samplev2 % docker compose up
http://localhost:3000/にアクセスしてみて次のような画面が表示されれば成功です。