Docker composeで既存のRailsアプリをdocker化する方法について

皆様こんにちは、Amiaです。

私はここ一ヶ月くらいDockerについて学習をしていました。
そのためアウトプットも兼ねてタイトルにある通り『既存のアプリをdockerする方法』ついて今回はブログを書いていきたいと思います。

よろしければご覧になっていただければと思います。

⚫︎今回の開発環境について

◎開発環境
・CPU:Apple M2
・OS:macOS 13.4.1

◎各種バージョン
ruby:3.2.2
rails:7.0.6
・postgres:12.0

※今回私が環境構築するにあたり使用したエディタおよびターミナルはVScodeです。

⚫︎手順全体像

詳細な手順に触れる前にまずは大まかな流れから確認していきましょう。
①今回対象のアプリを置くディレクトリを用意する。
②ターミナルを開き、アプリを置くディレクトリへ移動する。
③今回対象のRailsプロジェクトをGithubからクローン(コピー)してくる。
④③でクローンしてきたディレクトリの直下にDockerfileを作成する。
⑤④で作成したDockerfileを編集する。
⑥同ディレクトリ内でdocker-compose.ymlを作成する。
⑦⑥で作成したdocker-compose.ymlを編集する。
⑧configディレクトリ内にあるdatabase.ymlを変更する。
⑨ターミナルでDocker imageを作成する。
⑩ターミナルでコンテナを起動する。
⑪上記までとは別のターミナル画面を開く。
⑫ターミナルでデータベースを作成する。
Webブラウザ上でURL:http://localhost:3000にアクセスする。
⑭ターミナルでアプリケーションを終了させる。

⚫︎手順

それでは手順の詳細について記載していきたいと思います。

①今回対象のアプリを置くディレクトリを用意する。

こちらの工程については特に詳細な説明は不要かと思います。
アプリを置きたい場所にディレクトリを新しく作成するなり既存の場所に作成するなりお好きなようにしていただけたらと思います。

②ターミナルを開き、アプリを置くディレクトリへ移動する。

下記コマンドをターミナルで入力して①で用意したディレクトリに移動します。

cd <ディレクトリパス>
③今回対象のRailsプロジェクトをGithubからクローン(コピー)してくる。

下記のコマンドをターミナルで入力して今回対象のRailsアプリをクローンします。

git clone <リポジトリパス>
④③でクローンしてきたディレクトリの直下にDockerfileを作成する。

下記のコマンドをターミナルで入力して③でクローンしてきたディレクトリの直下にDockerfileを作成します。

touch Dockerfile
⑤④で作成したDockerfileを編集する。

Dockerfileを下記のように編集します。

FROM ruby:3.2.2
RUN apt-get update && apt-get install -y \
  build-essential \
  libpq-dev \
  nodejs \
  postgresql-client \
  yarn

  WORKDIR /rails-docker
  COPY Gemfile Gemfile.lock /rails-docker/
  RUN bundle install

今回のコードについて詳細をまとめていきたいと思います。

FROM ruby:3.2.2

FROMで作成するコンテナのベースとなるイメージを指定しています。今回の場合は「ruby」ですね。

RUN apt-get update && apt-get install

RUNでコンテナ内で実行されるコマンド指定します。apt-get updateでインストール可能なパッケージの一覧を更新します。apt-get installで指定したパッケージをインストールします。

WORKDIR /rails-docker

WORDKDIRを指定することで、以降の指令がそのディレクトリ内で実行されます。今回の場合ですと以降は作業ディレクトリが「/rails-docker」に変更されます。

COPY Gemfile Gemfile.lock /rails-docker/

COPYでbuild contextの中にあるDockerfile以外のファイルやフォルダをDocker Imageに組み込み、コンテナ内で使用できます。今回の場合ですとbuild contextの中にあるGemfileとGemfile.lockをコンテナ内の「/rails-docker/」配下にコピーしています。

RUN bundle install

bundle installはライブラリをインストールするコマンドです。また、ここでインストールするものがアプリ内で使えるかどうかをチェックしています。

⑥同ディレクトリ内でdocker-compose.ymlを作成する。

下記のコマンドをターミナルで入力して同ディレクトリ内にdocker-compose.ymlを作成します。

touch docker-compose.yml
⑦⑥で作成したdocker-compose.ymlを編集する。

docker-compose.ymlを下記のように編集します。

version: '3'

volumes:
 db-data:

services:
  web:
    build: .
    command: bash -c "rails db:migrate && rails s -p 3000 -b '0.0.0.0'"
    ports:
      - '3000:3000'
    volumes:
      - '.:/rails-docker'
    environment:
    - 'DATABASE_PASSWORD=postgres'
    tty: true
    stdin_open: true
    depends_on:
      - db
    links:
      - db

  db:
    image: postgres:12.0
    volumes:
      - 'db-data:/var/lib/postgresql/data'
    environment:
      - 'POSTGRES_USER=postgres'
      - 'DATABASE_PASSWORD=postgres'
      - 'POSTGRES_HOST_AUTH_MEtHOD=trust'

※インデントの位置に気をつけてください。私はこのせいでエラーが出てしまい、少し悩まされました(笑)

今回のコードについて詳細をまとめていきたいと思います。

version: '3'

docker-composeで使用するバージョンを定義します。

volumes:
 db-data:

ここでのvolumesはDocker Composeにボリュームを作成するように指示します。また、ここで定義されたボリュームはサービス内のvolumesで使用することができます。

services:

servicesでは全体の構成をするコンテナの設定をします。
今回では「web」と「db」ですね。

webサービスについて

build: .

webサービスのDocker imageをビルドする際の設定をします。
用意したDockerfileよりビルドする場合、build:へdocker-compose.ymlファイルが置いてあるディレクトリ(カレントディレクトリ)からDockerfileが置いてあるディレクトリへの相対パスを記述します。
build: .でdocker-compose.ymlと同じフォルダにDockerfileがあることを示します。

command: bash -c "rails db:migrate && rails s -p 3000 -b '0.0.0.0'"

commandwebサービスのコンテナが起動したときに実行するコマンドを指定します。 bash -c "rails db:migrate && rails s -p 3000 -b '0.0.0.0'"でデータベースにデータを反映してRailsのWebサーバーをポート番号3000で起動する。

ports:
      - '3000:3000'

ホストの「ポート番号」とコンテナの「ポート番号」の対応付けを定義します。 ホストのポート番号:コンテナのポート番号で指定します。

volumes:
      - '.:/rails-docker'

ホストのdocker-compose.ymlが配置されているディレクトリをコンテナ上の「/rails-docker」ディレクトリにマウント(共有)させます。ホストにもデータを共有することでデータの永続性を可能にしています。そのためコンテナが削除された場合でもデータは保持されたままになります。

environment:
    - 'DATABASE_PASSWORD=postgres'

Dockerコンテナ内で使用される環境変数を設定するため指定します。
Dockerコンテナはホストの環境と完全に分離されて動作するため、コンテナ内部で環境変数を設定する必要があります。

tty: true

出力を見やすくします。

stdin_open: true

標準入出力とエラー出力をコンテナと結びつける設定を指定します。

depends_on:
    - db

依存関係を定義してコンテナの起動順序を制御します。 今回の場合ですとwebサービスが起動する前にdbサービスが起動するように設定しています。

links:
    - db

コンテナを他のサービスにリンクするように設定します。

・dbサービスについて

image: postgres:12.0

Dockerイメージを指定することで、そのイメージよりコンテナを作成します。
ホストに存在しなければDocker Hubからイメージを取得し、それをもとにコンテナを作成します。
今回の場合ですとDocker Hubからpostgresのver.12.0のイメージを取得してそれをもとにコンテナを作成します。

volumes:
      - 'db-data:/var/lib/postgresql/data'

ホストのdb-dataをコンテナ上の「/var/lib/postgresql/data」ディレクトリにマウント(共有)させます。

environment:
      - 'POSTGRES_USER=postgres'
      - 'DATABASE_PASSWORD=postgres'
      - 'POSTGRES_HOST_AUTH_MEtHOD=trust'

webサービスの時と同様にDockerコンテナ内で使用される環境変数を設定するため指定します。

⑧configディレクトリ内にあるdatabase.ymlを変更する。

database.ymlを下記のように変更します。
⚫︎変更前

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

production:
  <<: *default
  database: myapp_production
  username: myapp
  password: <%= ENV["MYAPP_DATABASE_PASSWORD"] %>

⚫︎変更後

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  user: postgres
  password: <%= ENV.fetch("DATABASE_PASSWORD") %>
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: rails-docker_dev

test:
  <<: *default
  database: rails-docker_test

production:
  <<: *default
  database: rails-docker_prod

今回のコードについて詳細をまとめていきたいと思います。

adapter: postgresql

使用するデータベースの種類を指定します。

encoding: unicode

文字コードを指定します。

host: db

接続先のサーバ名またはIPアドレスを指定します。

user: postgres

ユーザー名を指定します。

password: <%= ENV.fetch("DATABASE_PASSWORD") %>

データベースに接続するパスワードを指定します。

database: rails-docker_dev

接続先のデータベース名を指定します。

⑨ターミナルで下記のコマンドを入力してDocker imageを作成する。
docker-compose build
⑩ターミナルで下記のコマンドを入力してコンテナを起動する。
docker-compose up
⑪上記までとは別のターミナル画面を開く。
⑫ターミナルで下記のコマンドを入力してデータベースを作成する。
docker-compose run --rm rails db:create
Webブラウザ上で下記のURLにアクセスする。

http://localhost:3000

画面が表示されていることをご確認ください。

⑭ターミナルでアプリケーションを終了させる。

ターミナルで下記のコマンドを入力してアプリケーションを終了させます。

docker-compose down

お疲れ様でした。
以上が『Docker composeで既存のRailsアプリをdocker化する方法』についてでした。

⚫︎最後に

Docker composeで既存のRailsアプリをdocker化する方法について記載してきました。今回の記事を書く中でもまだ理解が浅はかな部分があったため調べたりインプット教材を見直したりしました。まだまだ学習が足りないということを痛感しました。

Dockerを使用することで開発環境を簡単に構築することができます。とても便利なため1日でも早く使いこなすことができるようにしていきたいです。

以上、最後までご覧くださりありがとうございました。