※2022年から技術系の記事は個人ブログに投稿しております。ぜひこちらもご覧ください→yamaday0u Blog
以前書いた以下の記事の関連で、Docker環境とローカル環境両方でデータベースを使えるようにする設定について紹介します。
【Rails6/MySQL5】既存アプリにDocker環境を構築した方法(Capistrano・Amazon S3にも対応)
解決したいこと
rails s
コマンドを使いローカル環境でサクッとデータベースの動作を確認したい。
基本はdockerで立ち上げたコンテナ環境で動作確認しているけど、ちょこっとデータベースの動きを確認をするためだけにdockerを立ち上げるのが面倒と感じている。
開発環境・前提
- Ruby 2.6.5
- Rails 6.0.3.6
- Docker 20.10.6
- docker-compose 1.29.1
- mysql 5.6.50
docker-compose.ymlの記述
#docker-composeのバージョン
version: '3'
services:
db:
# 既存アプリとあわせる/ターミナルで[$ mysql --version]で確認
image: mysql:5.6.50
# 環境変数の設定
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: root
# ポート番号を指定/[ローカル:コンテナ]
ports:
- "4306:3306"
# 名前付きボリュームでDBのデータを永続化
# [データボリューム名:コンテナ内のパス]
volumes:
- mysql_data:/etc/mysql/conf.d
web:
# Dockerfileのパスをカレントディレクトリに指定
build: .
# server.pidファイルを削除してからrailsサーバー起動
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
# 環境変数の設定
environment:
- MYSQL_HOST=db
- MYSQL_PASSWORD=password
# ディレクトリのマウント
volumes:
- .:/group_calendar
ports:
# ポート番号を指定/[ローカル:コンテナ]
- 3000:3000
# サービス間の依存関係を指定
# この場合、db → webの順でサービスを起動
depends_on:
- db
# コンテナを起動させ続けるための設定
# make container stay launched
tty: true
# stdinはstandard input(標準入力)の略
# コンテナの外から命令を送るための設定
stdin_open: true
volumes:
# db:volumes:で作成したボリューム名を記述
mysql_data:
特に特別な記述はしていないのですが、注目ポイントはservices:db:environment:
以下の環境変数です。
後述のdatabase.yml
での記述に活かされます。
services:
db:
# 環境変数の設定
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: root
database.ymlの記述
default: &default
adapter: mysql2
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: <%= ENV['MYSQL_PASSWORD'] || '' %> # 記述箇所
socket: /tmp/mysql.sock
host: <%= ENV['MYSQL_HOST'] || 'localhost' %> # 記述箇所
解説
概要
password
とhost
のところの記述が肝です。
||
は比較演算子で、左側の値が真であればその値を返し、偽であれば右側の値を評価してその値を返します。
Ruby 3.0.0 リファレンスマニュアル 演算子式 or
左側の環境変数MYSQL_PASSWORD
とMYSQL_HOST
はdocker-compose.yml
で定義した環境変数です。
右側はrails s
コマンドでローカル環境を立ち上げるときに使用されるデータベースのhost
とpassword
の値です。
補足:順番も大事
左側にDocker環境用の変数を置き、右側にローカル環境用の値を置いていることにも意味があります。
もし、以下のように左側にローカル環境用の値を記述してしまうと、たとえdocker-compose up
でDocker環境を立ち上げたとしても、ローカル環境用のデーターベースに接続しようとしてしまい、接続エラーを起こしてしまいます。
default: &default
password: <%= '' || ENV['MYSQL_PASSWORD'] %> # 左右の順番を入れ替え
host: <%= 'localhost' || ENV['MYSQL_HOST'] %> # 左右の順番を入れ替え
その理由はDocker環境の外にあるローカル環境のデータベースに接続することができないからです。
これを回避するために、Docker環境用のデータベースに接続するための記述を比較演算子の左側に記述する必要があります。
rails s
でローカル環境を立ち上げる場合は、ローカル環境に環境変数MYSQL_PASSWORD
とMYSQL_HOST
の値がなく「偽」となるため、右側の値が返されるという仕組みになっています。