30代中盤・未経験からGoエンジニアを目指す人のブログ

~プログラミング関連、勉強法などから雑記まで赴くままに~

Webアプリ (rails) をDockerとDocker ComposeでDocker化する方法

Dockerはアプリケーションを軽量なコンテナとしてパッケージ化し、どこでも動作させることができる便利なツールです。
 
この記事では、まだまだ初学者ではある私ですが既存のwebアプリを任意のlocal環境で動作させる為のdocker化を覚えましたので、他者様が作った既に完成しているwebアプリをDockerとDocker Composeを使用してDocker化してlocalで起動する手順を解説したいと思います。
 
今回は railsアプリ、またdbはPostgreSQLを使用します。 
 

追加で必要なファイルは2つ、修正するファイルは1つ 

既存webアプリのdocker化の大まかな流れ
 
1. Dockerfileの作成
2. docker-compose.ymlの作成
3. database.ymlファイルの一部修正
4. Dockerイメージのビルド
5. データベースのセットアップ
6. アプリケーションの起動
7. localhost:3000にアクセス
   
まず手順だけ先に書き、その下に各解説を書いていきます。 
 

1. Dockerfileの作成

まず、railsアプリのルートディレクトリ(README.mdやGemfileがあるディレクトリ)にDockerfileを作成、中身は下記の通り。
# 以下、[app_name]はご自身で用意したアプリのルートディレクトリ名に変えて記入してください
# インデントが大事なので十分注意してください

FROM ruby:3.2.2 #任意のバージョンを指定してください
RUN apt-get update -qq && apt-get install -y \  
  build-essential \
  libpq-dev \
  node.js

WORKDIR /app_name
COPY Gemfile Gemfile.lock /app_name/

RUN gem install bundler && bundle install

COPY . /rails-docker/

 

2. docker-compose.ymlの作成

docker-compose.ymlファイルをアプリのルートディレクトリ(先程作ったDockerfileと同じディレクトリ)に作成し、中身は下記の通り。
# 以下、[app_name]はご自身で用意したアプリのルートディレクトリ名に変えて記入してください
# インデントが大事なので十分注意してください

version: "3"

volumes:
  postgresql-data:

services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    environment:
      - "POSTGRES_USER=postgres"
      - "POSTGRES_PASSWORD=postgres"
    tty: true
    stdin_open: true
    volumes:
      - .:/app_name
    ports:
      - "3000:3000"
    depends_on:
      - db

  db:
    image: postgres:12 #任意のバージョンを指定してください
    environment:
      - "POSTGRES_USER=postgres"
      - "POSTGRES_PASSWORD=postgres"
    ports:
      - "5432:5432"
    volumes:
      - postgresql-data:/var/lib/postgresql/data

 

3. database.ymlファイルの一部修正

/app_name(用意したアプリ)/config/databse.ymlの中の
一部記述(default: &defaultから下部の数行)を以下のように変更します。

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: postgres
  port: 5432
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

 

4. Dockerイメージのビルド

Dockerfileが正しく設定されたら、次のコマンドでDockerイメージをビルドします。

$ docker-compose build

※初回はビルドもするので処理が終わるまで数分かかります。
また、途中でダウンロードが失敗しエラーが出ることもあります(私も一度なりました)が、
再度$ docker-compose buildを行うことでダウンロード含め、処理は成功します。  
 

5. データベースのセットアップ

$ docker-compose run --rm web rails db:create

 

6. アプリケーションの起動

$ docker-compose up

次回以降は5.のデータベースのセットアップは必要なくこの$ docker-compose up1行を実行するだけでアプリケーションを起動できます。  
 

7. localhost:3000にアクセス

$ docker-compose up後、シェルはそのままの状態(アプリケーションが起動している状態)で、http://localhost:3000にてアプリケーションが動作しているはずですので、
http://localhost:3000にアクセスするとwebアプリケーションとして使用開始できます。
 
終了方法は$ docker-compose upを行ったシェルに戻り、cmd + c (ctrl + c)を押すと終了します。
再度起動するときはシェルで$ docker-compose upを実行するだけ。

 
以上が流れです。

解説はこちら↓

Dockerfile

FROM ruby:3.2.2 #任意のrubyバージョンを選択
RUN apt-get update -qq && apt-get install -y \ 
  build-essential \ 
  libpq-dev \ 
  node.js 
# イメージのビルド時にOSのパッケージリストを更新と下記パッケージ郡をインストール
# build-essential: コンパイラやライブラリなどの開発に必要な基本的なパッケージ群
# libpq-dev: PostgreSQLデータベースを扱うためのライブラリ
# node.js: JavaScriptのランタイム環境であるNode.js


WORKDIR /app_name 
#以降のコマンドは、/app_nameディレクトリ内(アプリのルートディレクトリ内)で実行
COPY Gemfile Gemfile.lock /app_name/ 
# ホストのGemfileとGemfile.lockをコンテナの/app_nameディレクトリにコピー
# 複数のファイルをコピーする際はapp_nameの後ろに`/`が必要

RUN gem install bundler && bundle install 
# 最新のbundlerをインストールした後、コピーしたGemfileとGemfile.lockをもとに必要なRubyのライブラリをインストール

COPY . /rails-docker/
# ホストの現在のディレクトリ全内容をコンテナの/app_name/にコピー

 
docker-compose.yml

version: "3"
# 使用するDocker Composeのファイル形式のバージョン(ほとんど3なのでこう書くものだと思ってオッケー)

volumes:
  postgresql-data:
# postgresql-dataという名前のボリュームを定義

services:
# このComposeファイルで定義するサービス群を示します。具体的には次のインデントのwebとdb。
# この2つがそれぞれコンテナ化されて相互に利用される。
  web:
  webという名前のサービスを定義(アプリ側)
    build: .
    # webサービスのDockerイメージを、現在のディレクトリ( . )にあるDockerfileを使用してビルド
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    # webサービスを起動する際のコマンドを指定。railsサーバーを起動、ポートは3000(railsのデフォルト)
    environment:
      - "POSTGRES_USER=postgres"
      - "POSTGRES_PASSWORD=postgres"
    # 環境変数を設定。PostgreSQLのユーザ名とパスワードを指定
    tty: true
    # ttyを有効にします。これにより、コンテナ内でのインタラクティブな操作が可能に
    stdin_open: true
    # 標準入力をオープンします。これもインタラクティブな操作のため
    volumes:
      - .:/app_name
    # ホストの現在のディレクトリ( . )と、コンテナの/app_nameディレクトリをマウント(同期)する
    ports:
      - "3000:3000"
    # ホストの3000番ポートと、コンテナの3000番ポートを紐づけし、
    # localhost:3000にアクセスした時にコンテナにアクセス
    depends_on:
      - db
    # webサービスはdbサービスに依存しているため、dbサービスが先に起動するように指定
    # これにより、dbが起動してからrailsサーバーを起動するコマンドを行うようにする

  db:
    image: postgres:12 #任意のバージョンを指定してください
    environment:
      - "POSTGRES_USER=postgres"
      - "POSTGRES_PASSWORD=postgres"
    ports:
      - "5432:5432"
    # ホストの5432番ポートと、コンテナの5432番ポートを紐づけ。これはPostgreSQLのデフォルトのポート番号
    volumes:
      - postgresql-data:/var/lib/postgresql/data
    # 先に定義したpostgresql-dataボリュームとコンテナ内のPostgreSQLのデータディレクトリ/var/lib/postgresql/dataをマウント
    # これにより、データベースのデータが永続化可能に

  
docker-composeコマンド

$ docker-compose build

# Dockerfileを元にdocker imageをビルド

   
データベースの設定

docker-compose run --rm web rails db:create
# 初回アプリ起動前にデータベースの作成が必要(コマンド`$ rails db:create`)、このコマンドをwebコンテナのrailsに対して指示するコマンドの書き方が上記になる  
また、--rmオプションをつけることで、コマンドが終わりコンテナからexitされたらこのコンテナが自動で削除されるように設定。

 
アプリケーションの起動

`docker-compose.yml`内のコマンド`bundle exec rails s -p 3000 -b '0.0.0.0'`でrails serverの起動も行っているため、  
`$ docker-compose up`1行で完結するようになっている

 

まとめ

DockerとDocker Composeを使用してWebアプリをDocker化する方法を解説しました。この手順を参考にあなたもrailsアプリをDocker環境での動作確認をしてみてください。