はじめに
Railsを使った開発で、Dockerを採用する事はよくある事だと思います。
Rails・DBの両方をDockerでコンテナ化する選択肢もあるようですが、立ち上げや通信がかなり遅くなるため(やり方によってはかなり高速にできるようですが)、今回はDocker Composeを使ってDBのみコンテナ化する環境構築の手順をメモしたいと思います。
開発環境
macOS Catalina バージョン10.15.7
ruby: 3.0.0
rails: 6.1.1
docker: 20.10.2
Dockerをインストール
Docker HubからDockerをインストールします。
https://hub.docker.com/editions/community/docker-ce-desktop-mac/
# インストールできたか確認
docker version
私の場合、バージョンは20.10.2でした。
Railsプロジェクトを生成
グローバルを汚さないRails環境構築の方法を別記事にしてますので、よければ参考にして下さい。
Railsの環境構築(グローバル環境を汚さずに) - Qiita
bundle exec rails . new -d mysql
こちらの実行。
-d mysql
で使用するDBをMySQLに指定しています。指定しないとデフォルトでSQLiteが使われます。
エラーが出ました、、、
...
checking for MYSQL_OPTION_MULTI_STATEMENTS_ON in mysql.h... yes
checking for MYSQL_OPTION_MULTI_STATEMENTS_OFF in mysql.h... yes
checking for my_bool in mysql.h... no
-----
Don't know how to set rpath on your system, if MySQL libraries are not in path mysql2 may not load
-----
...
2 warnings generated.
compiling infile.c
compiling mysql2_ext.c
compiling result.c
compiling statement.c
linking shared-object mysql2/mysql2.bundle
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1
...
An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'` succeeds before bundling.
In Gemfile:
mysql2
run bundle binstubs bundler
Could not find gem 'mysql2 (~> 0.5)' in any of the gem sources listed in your Gemfile.
rails webpacker:install
Could not find gem 'mysql2 (~> 0.5)' in any of the gem sources listed in your Gemfile.
bundle install
でmysql2をインストール時にエラってる模様。
rails mysql インストールエラーみたいな感じでググってみると、
BUNDLE_BUILD__MYSQL2: "--with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include"
これを.bundle/config
に記載して、bundle install
でいけました。
https://nyakanishi.work/bundle-install%E6%99%82%E3%81%ABmysql2%E3%81%A7%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%97%E3%81%9F%E6%99%82%E3%81%AE%E5%AF%BE%E5%BF%9C/
何をやってるかと言うと、bundle install
時の環境変数を設定しています。
どうやらAppleはopensslを推奨しておらず、独自のライブラリを優先して使うらしいので、opensslを指定しないとうまく動かないらしい。
ちなみに上のコマンドのかわりに、
export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/opt/openssl/lib/
こっちでもいけるっぽいです。
docker-compose.ymlを作成
railsプロジェクトのルートディレクトリで、docker-compose.ymlを作成します。
version: '3'
services:
db:
container_name: sample-db
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: 'password'
MYSQL_DATABASE: sample
TZ: "Asia/Tokyo"
ports:
- '7306:3306'
volumes:
- ./docker/config/my.cnf:/etc/mysql/conf.d/my.cnf
- ./docker/storage/db:/var/lib/mysql
version
docker-composeファイルのバージョンを指定。今の最新は3系なので3系を指定。
services
コンテナ化する要素をネストして記載する。
db
コンテナ要素。名前はdb出なくても何でも良いです。
container_name
コンテナの名前を指定してます。指定しないとdocker ps
などで対象コンテナが分かりづらくなるため指定していた方がいいとも思います。
image
docker hubに上がっているDockerImageを指定しています。
emvironment
環境変数を定義しています。
ports
ローカル環境とコンテナ内のポート番号を指定しています。
プロジェクト毎に複数コンテナを立てることを想定しているので、ローカル環境側のポートを適当な数字にしています。プロジェクト毎に6303:3306
, 6306:3306
などローカル側を違うポートにすることで複数のコンテナでdbサーバを起動できます。
volumes
コンテナ内のデータをローカルにマウントして永続化します。ローカル:コンテナ内
で書きます。こうする事でコンテナが破棄されてもデータは残り再びコンテナを立てればデータを利用できます。docker-compose up
で自動的にdocker/config/my.cnf
とdocker/storage/db/
が生成されます。db/
には色々自動生成されるものが入ると思いますが、my.cnf
は自分で設定を書かなければいけないので、このタイミングで作成しておきます。
# 必要な設定を記述
[mysqld] # mysqlサーバーへの設定
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
explicit_defaults_for_timestamp = 1
[client] # mysqlクライアントツールへの設定
default-character-set=utf8mb4
コンテナ起動
docker-compose up
別タブでコンテナ内に入ってみましょう。
mysql sample -h 127.0.0.1 -u root -P 7306 -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.30 MySQL Community Server (GPL)
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
MYSQL_ROOT_PASSWORD
のパスワードでログインできます。
成功したらexit;
で抜けておきましょう。
rails側の設定
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: password
host: 127.0.0.1
port: 7306
development:
<<: *default
database: sample_development
bundle exec rails db:create
createが成功すればOKです。
終わりに
dockerでMySQLをコンテナ化している場合、ホストをlocalhost
にすると接続できません。
最初database.yml
に127.0.0.1
ではなくlocalhost
と記載していてかなり詰まりました。