Hirologue

年齢を理由にエンジニアになることを諦めないミドルの成長記録

EP 11: 既存のWebアプリをDocker化してみる

はじめに

Dockerと聞いて、何だか難しそうとか何がいいのかわからないという方もいるかと思います。
私もそのうちの一人でした。 過去にUdemyなどでDockerについて学習した経験はありますが、正直学んだというだけで、ほとんど身についていませんでした。
Dockerを使えるようになると、例えばPCを買い替えてこれまでの開発環境をイチから構築し直すといった手間も省けたりとメリットが多いことは重々承知していました。
わかっているけど動き出せないのも事実でした。

今やDockerはバズワードではなく、いまやデファクトスタンダードであるという事実を知りました。
本気でエンジニアを目指すなら避けては通れない道であるなら、嫌だとは言っていられない。
そんな背景もあって、今回あらためてDockerを学び直したところ、既存のWebアプリをDocker化することができました。

そもそもDockerってなんだ?という方は、こちらのブログをご覧ください。

datawokagaku.com

本記事では、既存のWebアプリをDocker化する手順について紹介します。
なお、Docker化する既存のアプリは、手元にあることが前提となりますことをご了承ください。

Docker化の手順

Docker バージョン

使用したDockerのバージョンは以下の通りです。

  • Docker version: 26.1.1
  • Docker Compose version: v2.27.0

Rubyバージョンの確認と使用するDB

今回は、Ruby on Railsで作成されたWebアプリをGitHubから$ git cloneして使用しました。
では、作業ディレクトリに移動して、内容を確認します。
GemfileというファイルにRubyのバーションについて記述がありました。
どうやら、Rubyのバージョンは、3.2.2 のようです。
ということで、今回は Ruby 3.2.2を使用することに決めました。

また、config/database.yml 内に、次のようなコメントを発見しました。
PostgreSQL. Versions 9.3 and up are supported.”
そこで、データベースは Postgresql バージョン12 を使用することにしました。

Dockerfileの新規作成

次に行うのは、Dockerfileの新規作成です。
Ruby 3.2.2をベースにして、各種パッケージをインストールする必要があります。
作成過程は割愛しますが、完成した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



次は、このDockerfileのイメージをビルドし、実際に動くか確認します。

# Dockerイメージを作成
$ docker build .

# IMAGE IDの確認
$ docker images

# コンテナを起動してbashを実行
$ docker run -it <IMAGE ID> bash

bashlsコマンドやruby -vなどを実行してみて動作確認を行います。

docker-compose.ymlの作成 - 1

次にdocker-compose.ymlを作成して、Railsアプリケーション(app)とデータベース(db)の設定を行います。
こちらも作成過程は割愛しますが、このようになります。

# version: '3'

volumes:
  db-data:

services:
  app:
    build: .
    ports:
      - '3000:3000'
    volumes:
      - '.:/rails-docker'
    environment:
      - 'DATABASE_PASSWORD=postgres'
    tty: true
    stdin_open: true
    depends_on:
      - db
    links:
      - db

  db:
    image: postgres:12
    volumes:
      - 'db-data:/var/lib/postgresql/data'
    environment:
      - 'POSTGRES_USER=postgres'
      - 'POSTGRES_PASSWORD=postgres'

1行目のversion: 3については、現行のDocker Composeのバージョンでは記述不要となったようです。 記述すると警告文が表示されるので、コメントアウトしています。
Webアプリなので、データを永続化させるためにvolumesを設定しました。
appのポート番号はRailsのデフォルトのポート番号 3000を使用しました。
dbについては、postgresqlのバージョン12をイメージとして使用するように設定しました。

また、appとdb で必要な環境変数も設定しました。

database.yml の設定

次にconfig/database.ymlに設定を追記します。
追記する内容は 、host, user, port, password で、追記部分は次のようになります。

default: &default
  adapter: postgresql
  encoding: unicode
  
  # 以下の4行を追記
  host: db
  user: postgres
  port: 5432
  password: <%= ENV.fetch("DATABASE_PASSWORD") %>

これでアプリを起動させる準備が整いました。

アプリケーションの起動

まずはターミナルから起動します。

linuxコマンドで色々設定したいので、今回は-dオプションを付けてコンテナを起動します。

# コンテナの起動
$ docker-compose up -d

# コンテナ内のbashを起動
$ docker-compose exec app bash

次にデータベースの作成とマイグレーションを行います。

$ rails db:create

$ rails db:migrate

これで、やっとRailsサーバーを起動させることができます。コマンドは次の通りです。

$ rails s -b 0.0.0.0

正常に起動したのが確認できたら、今度は、Webブラウザを立ち上げてアドレスバーにlocalhost:3000と入力します。
これで、アプリを表示することができました👏

終了するには、$ docker-compose downコマンドを入力して、コンテナを停止して削除します。

・・・・・・何だか、手数が多いな、と不便さを感じたのではないでしょうか?
少なくとも私は面倒だなと思いました。

docker-compose.ymlの作成 - 2

コンテナ起動後の手数を減らすために、$ docker-compose up -d実行後のコマンドをdocker-compose.ymlに追記します。

# version: '3'

volumes:
  db-data:

services:
  app:
    build: .
    ports:
      - '3000:3000'
    volumes:
      - '.:/rails-docker'
    environment:
      - 'DATABASE_PASSWORD=postgres'
    tty: true
    stdin_open: true
    depends_on:
      - db
    links:
      - db

    # 追記したコマンド
    command: bash -c "rails db:create && rails db:migrate && rails s -b 0.0.0.0"

  db:
    image: postgres:12
    volumes:
      - 'db-data:/var/lib/postgresql/data'
    environment:
      - 'POSTGRES_USER=postgres'
      - 'POSTGRES_PASSWORD=postgres'

$ docker-compose upコマンドを実行して、コンテナを起動させます。
サーバーが起動したのを確認したら、先ほどと同様にWebブラウザのアドレスバーにlocalhost:3000 を入力してみます。
エラーがなくアプリが動作したらDocker化の成功です。

docker-compose.ymlの修正(2024/06/02 追記)

ここまでの工程で、一見するとDocker化が成功と思いますが、追記したコマンドを良く見てみます。

# 追記したコマンド
    command: bash -c "rails db:create && rails db:migrate && rails s -b 0.0.0.0"

実はこのままだと、初回起動時にはrailsコマンドの入力を省略できて、楽なのですが2回目以降の起動時にもデータベースを作成しようとしてしまいます。
なので、追記したコマンドからrailsコマンドは削除します。
修正後のdocker-compose.ymlファイルはこのようになります。

# version: '3'

volumes:
  db-data:

services:
  app:
    build: .
    ports:
      - '3000:3000'
    volumes:
      - '.:/rails-docker'
    environment:
      - 'DATABASE_PASSWORD=postgres'
    tty: true
    stdin_open: true
    depends_on:
      - db
    links:
      - db

    # 修正したコマンド
    command: bash -c "rails s -b 0.0.0.0"

  db:
    image: postgres:12
    volumes:
      - 'db-data:/var/lib/postgresql/data'
    environment:
      - 'POSTGRES_USER=postgres'
      - 'POSTGRES_PASSWORD=postgres'

このようにコードを修正し、初回起動時だけ手間ですが、次のコマンドを入力します。

# コンテナの起動
$ docker-compose up -d

# コンテナ内のbashを起動
$ docker-compose exec app bash

# データベースの作成
$ rails db:create

# マイグレーションの実行
$ rails db:migrate

この操作を行ってから localhost:3000 にアクセスします。

初回起動時のこの手順については、READMEにしっかりと記述します。




いかがだったでしょうか。
このようにすることで、ローカルにRubyの実行環境がなくともコンテナ内でRailsアプリを起動させることができました。
Dockerを使いこなせるようになるには、いろいろと環境構築してみるのがベストプラクティスのように思えます。 本記事を読んで、Docker便利そうだから勉強してみようと思っていただけたら幸いです。

では✋