はじめに
Dockerの公式Tutorialでは、DB:PostgreSQLで解説されている為、他のDB(例:MySQL)でDockerを導入してみたい初学者にとってはややハードルが高い状況です。
本記事では、途中まで作ったRailsアプリ(DB:MySQL)にDockerを導入する方法を解説します。
Dockerを途中から導入するアプリの例としては、scaffoldで作成した
簡単な蔵書管理アプリ(bookapp)を使用します。
(適宜、ご自身で開発中のアプリに置き換えて頂ければと思います)
DBはMySQL5.7で実装を進めます。
併せてDocker環境でもDB内容を視覚的に確認できるように
SequelProとの接続方法も解説します。
前提
- macでDockerが既に導入されている
Dockerインストールはこちらの記事が分かりやすいです。
DockerをMacにインストールする - Sequelpro インストール済
Sequelproの解説記事はこちら
データベースの操作がGUIで分かりやすく操作できるSequel Proの最低限の使い方
目指すゴール
(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を以下のように編集します。
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を以下のように編集します。
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つを追記してください。
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/
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_USERNAME=root
DB_PASS=password
DB_HOST=db
MYSQL_ROOT_PASS=password
2)database.ymlを編集
上記で追加した環境変数を読み込む為、config/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)を追加してください。
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接続設定のページを開いてください。
Dockerコンテナ用の接続設定を追加する
設定ページが開けたら以下のようにDockerコンテナ用の接続設定を追加してください。
「名前」・・・任意の名前で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でテーブル内容を確認できます。
参考記事
Docker 公式Tutorial
丁寧すぎるDocker-composeによるrails5 + MySQL on Dockerの環境構築(Docker for Mac)
既存のRailsアプリにDockerを導入する手順
Dockerで利用する環境変数をenv_fileを利用して一元管理する方法