38
49

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Ruby on Rails 「途中まで作ったアプリにDockerを導入したい」に挑戦してみる(MySQL / Sequel Pro)

Last updated at Posted at 2020-01-13

はじめに

Dockerの公式Tutorialでは、DB:PostgreSQLで解説されている為、他のDB(例:MySQL)でDockerを導入してみたい初学者にとってはややハードルが高い状況です。

本記事では、途中まで作ったRailsアプリ(DB:MySQL)にDockerを導入する方法を解説します。

Dockerを途中から導入するアプリの例としては、scaffoldで作成した
簡単な蔵書管理アプリ(bookapp)を使用します。
(適宜、ご自身で開発中のアプリに置き換えて頂ければと思います)

DBはMySQL5.7で実装を進めます。

併せてDocker環境でもDB内容を視覚的に確認できるように
SequelProとの接続方法も解説します。

前提

目指すゴール

(1) 既存のRailsアプリにMySQLを使ったDocker環境を構築する

(2) Sequelproと接続し、Docker環境でもGUIでDB内容を確認できるようにする

実装の流れ

1 Dockerfile/docker-compose.ymlを作成

2 Dockerfileを編集

3 docker-compose.ymlを編集

4 database.yml編集

5 コンテナをbuildする docker-compose build

6 Dockerコンテナ上でDB作成&migrationを実行
 docker-compose run web bundle exec rake db:create / db:migrate

7 コンテナを起動する docker-compose up

8 DB接続設定を環境変数に置き換え - env_file

9 Docker環境のRailsアプリとSequelProを接続する

1 Dockerfile/docker-compose.ymlを作成

まずは既存アプリに必要なファイルを追加します。
具体的には(1)Dockerfile (2) docker-compose.ymlの2ファイルです。

アプリのルートディレクトリに以下のように2つのファイルを追加してください。
(ファイルの作成場所に注意してください)

bookapp ----|-- app
            |-- bin
            |-- config
            |-- db
            ・・・・・・
       ・・・・・・
            |-- Gemfile
            |-- Gemfile.lock
            |-- package.json
            |-- Rakefile
            |-- README.md
            |-- Dockerfile  #ここに追加
            |-- docker-compose.yml #ここに追加          

[解説]
Gemfile/Gemfile.lockについて
・アプリ開発当初からDockerを導入する記事では、ここでGemfile(railsのみ導入)/Gemfile.lock(空でOK)を作成するように記載されていますが、既に開発中のアプリで作成済かと思いますのでGemfileについては特に何もしなくてOKです。

2 Dockerfileを編集

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

Dockerfile
FROM ruby:2.5

RUN apt-get update -qq && \
    apt-get install -y build-essential \ 
                       libpq-dev \        
                       nodejs      

RUN mkdir /app_name 

ENV APP_ROOT /app_name 
WORKDIR $APP_ROOT

ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock

RUN gem install bundler 
RUN bundle install
ADD . $APP_ROOT

[解説]
RUN gem install bundlerについて
Railsアプリに途中からDockerを導入する場合、Gemfileが既にある関係で上記のコマンド無しで進めようとするとエラーが出るかもしれません。(自分の環境ではBuildした時に以下のようなエラーが出ました)

ERROR: Service 'web' failed to build: The command '/bin/sh -c bundle install' returned a non-zero code: 20

対策として、DockerfileをBuildする際にbundlerを導入しておきます。

3 docker-compose.ymlを編集

続いて docker-compose.ymlを以下のように編集します。

docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: 'password'
    ports:
      - "4306:3306"

  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app_name
    ports:
      - "3000:3000"
    depends_on:
      - db

[解説]
1 db:portsの設定について- "4306:3306"
DockerコンテナとSequelpro接続の為に必要な設定です。(詳細は後ほど)
とりあえず現段階では、上記の設定にしておいてください。

2 rm -f tmp/pids/server.pidについて
開発途中に何度もdockerコンテナの起動&停止を繰り返していると時々「A server is already running.」のエラーが出ます。(pidファイルが残っていることが原因)
上記コマンドでserver.pidを逐一削除することで未然にエラーを防ぎます。

関連記事
docker-compose upしたときに「A server is already running.」って言われないようにする

4 database.yml編集

次にconfig/database.ymlの設定をdocker-compose.ymlの内容に合わせます。
具体的には(1) password (2)host:dbの2つを追記してください。

config/database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  socket: /tmp/mysql.sock
  host: db  

development:
  <<: *default
  database: bookapp_development

5 コンテナをbuildする docker-compose build

ここまで来たら、次はDocker環境のコンテナを作っていきます。
ターミナルで以下のコマンドを実行してください。
(初めて実行するときは少し時間がかかります)

[bookapp] $ docker-compose build 

6 Dockerコンテナ上でDB作成&migrationを実行

buildが無事完了したら、次はDB作成&migrationです。
ターミナルで以下のコマンドを実行してください。

[bookapp] $ docker-compose run web bundle exec rake db:create
Created database 'bookapp_development'
Created database 'bookapp_test'

[bookapp] $ docker-compose run web bundle exec rake db:migrate

== CreateBooks: migrating ======================================
-- create_table(:books)
   -> 0.0150s
== CreateBooks: migrated (0.0152s) =============================

[解説]
Dockerコンテナはlocalとは環境が異なります。
その為、再度DB作成&migrationの実行が必要になります

docker-compose run webコマンドについて
Dockerコンテナでのrailsコマンドは通常のコマンドの前に
「docker-compose run web」をつけて実行する必要があります。
通常のlocal環境のように「rake db:migrate」のみでは
変更が反映されないので注意してください。

7 コンテナを起動する docker-compose up

ここまで来たら、ブラウザでTopページ表示が可能になります。

まず以下のコマンドでDockerコンテナを立ち上げます。

[bookapp] $ docker-compose up 
Starting bookapp_db_1 ... done
Recreating bookapp_web_1 ... done

コンテナが立ち上がった後、ブラウザでTopページが表示されるか確認してみてください。
http://localhost:3000/

image.png

8 DB接続設定を環境変数に置き換え - env_file

ここまでの作業でDocker開発環境の構築は完了ですが、
DB接続関連の設定がファイルにベタ打ち(ハードコーディング)になっているのが
気になる方もいらっしゃるかもしれません。

Docker開発でも環境変数でDB接続関連の設定を読み込むことが可能です。

具体的には以下3つの作業を実施します。

(1) envファイル(db.env)を作成
(2) database.ymlを編集
(3) docker-compose.ymlを編集

1)envファイル(db.env)を作成

Dockerfileと同じルートディレクトリにenvファイルを作成します。
本記事ではファイル名を「db.env」とします。
以下ファイルを追加してください。

db.env
DB_USERNAME=root
DB_PASS=password
DB_HOST=db
MYSQL_ROOT_PASS=password

2)database.ymlを編集

上記で追加した環境変数を読み込む為、config/database.ymlを編集します。

database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch('DB_USERNAME', 'root') %>
  password: <%= ENV.fetch('DB_PASSWORD', 'pass') %>
  socket: /tmp/mysql.sock
  host: <%= ENV.fetch('DB_HOST', 'db') %>

development:
  <<: *default
  database: bookapp_development

[解説]
ENV.fetch(第一引数, 第二引数)について
第一引数に「環境変数」、第二引数に「デフォルト値」をセットします。
環境変数がnullの場合は第二引数のデフォルト値が読み込まれます。

3)docker-compose.ymlを編集

仕上げにdocker-compose.ymlの設定を変更します。
db、webの2箇所にdb.envを読み込む設定(env_file)を追加してください。

docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    ports:
      - "4306:3306"
    env_file: db.env

  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app_name
    ports:
      - "3000:3000"
    depends_on:
      - db
    env_file: db.env

ここまで出来たら一度コンテナを停止&再起動し、
環境変数経由でもTopページが表示できることを確認します。

# docker-compose stop or ctrl+Cでコンテナの停止が可能です。
Stopping bookapp_web_1 ... done
Stopping bookapp_db_1  ... done

#コンテナを再起動
[bookapp] $ docker-compose up
Starting bookapp_db_1 ... done
Starting bookapp_web_1 ... done

9 Docker環境のRailsアプリとSequelProを接続する

それでは最後にDockerコンテナとSequelProを接続してみましょう。

以下のSequelPro接続設定のページを開いてください。

image.png

Dockerコンテナ用の接続設定を追加する

設定ページが開けたら以下のようにDockerコンテナ用の接続設定を追加してください。

image.png

「名前」・・・任意の名前でOKです。ここでは「docker-sql」としています。
「ホスト」・・・「127.0.0.1」
「ユーザー名/パスワード」・・・envファイルに合わせて記載してください。
「ポート」・・・ 「4306」で設定します。

[解説]
ポート:4306について
docker-compose.ymlのポート設定を思い出してください。

ports: "4306:3306"

これはホストが4306で接続した時にコンテナ上では3306に置き換えるという意味になります。 
localhostのMysqlのデフォルトのポート番号は3306です。
その為ポート番号:3306をそのまま使うと競合が発生して接続エラーが起こります。

エラー回避の為、上記のようにDocker環境ではポート:4306を使ってSeqelProに接続する設定にします。

上記設定が完了したら、早速確認してみましょう。
dockerコンテナが起動している状態でSequelProの「接続」をクリックします。

無事接続できていれば以下のようにDocker環境でもGUIでテーブル内容を確認できます。

image.png

参考記事

Docker 公式Tutorial
丁寧すぎるDocker-composeによるrails5 + MySQL on Dockerの環境構築(Docker for Mac)
既存のRailsアプリにDockerを導入する手順
Dockerで利用する環境変数をenv_fileを利用して一元管理する方法

38
49
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
49

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?