Dockerで開発環境に使用するMySQLを用意する

Rails 環境でSQLサーバーを用意する場合、標準だとSQLiteになっています。
開発環境として、MySQLを使用することもできますが、システムにインストールするとそのうちDB名がぶつかる可能性も考えられます。

なので、今回はDockerでMySQLを準備してみます。


参考

実行環境

  • macOS Mojave 10.14.4

そもそもRailsからMysqlへの接続の仕方

Railsから、MySQLに接続するには方法が2つある。
それぞれで、config/database.ymlの書き方が異なる。

TCP(ローカルインストールMySQL)

IPとポートを指定して接続するパターン。
hostとportを指定する。

config/database.yml(development抜粋)
1
2
3
4
5
6
7
8
9
10
11
12
default: &defalt
adapter: mysql2
pool: <%= ENV.fetch("RAILS_MAX_THREADS")%>
timeout: 5000
encoding: utf8

development:
database: mysql_developmentDB
username: [任意のID]
password: [任意のパスワード]
host: 127.0.0.1 #ここを指定するlocalhostか127.0.0.1
port: 3306 #ここを指定する

UNIXドメインソケット(ローカルインストールMySQL)

UNIXドメインソケットを使用して接続するパターン。
socketを指定する。

config/database.yml(development抜粋)
1
2
3
4
5
6
7
8
9
10
11
default: &defalt
adapter: mysql2
pool: <%= ENV.fetch("RAILS_MAX_THREADS")%>
timeout: 5000
encoding: utf8

development:
database: mysql_developmentDB
username: [任意のID]
password: [任意のパスワード]
socket: /tmp/mysql.sock #ここを指定する

以上でmysqlの接続の方法を確認できました。
これを踏まえて、DockerでMySQLを用意します。
作成するDockerコンテナの元イメージはmysql Docker Official Imagesを使用します。


Dockerイメージ入手

以下コマンドでdockerイメージを入手します。

1
docker pull mysql


DockerでMySQLを用意してみる

今回も、TCPとUNIXドメインソケットそれぞれを試します。

TCP(Docker構築MySQL)

以下コマンドでDockerコンテナ作成と起動をします。

1
2
3
4
5
6
7
8
9
10
11
# コンテナの作成
# -p 3306:3306
# ポートリダイレクトの設定
# ローカルマシンのポート3306をコンテナのポート3306に転送する
#
# -e MYSQL_ROOT_PASSWORD=[任意のパスワード]
# パスワード設定
docker create --name mysql_tcp -p 3306:3306 -e MYSQL_ROOT_PASSWORD=[任意のパスワード] mysql

# コンテナの開始
docker start mysql_tcp

これでコンテナが起動する。

ここでTCP用の設定をconfig/database.ymlに以下の通り入力する。

config/database.yml(development抜粋)
1
2
3
4
5
6
7
8
9
10
11
12
default: &defalt
adapter: mysql2
pool: <%= ENV.fetch("RAILS_MAX_THREADS")%>
timeout: 5000
encoding: utf8

development:
database: mysql_developmentDB
username: [任意のID]
password: [任意のパスワード]
host: 127.0.0.1 #ここを指定するlocalhostか127.0.0.1
port: 3306 #ここを指定する

以下の通り、入力してrailsアプリを起動します。

1
2
3
4
# DB作成
bundle exec rails db:create
# Railsアプリの開始
bundle exec rails s

これでコンテナ上のMySQLにTCPで接続してRailsアプリが起動します。

UNIXドメインソケット(ローカルインストールMySQL) できなかった

コンテナ上のMySQLが作成しているmysql.sockの作成先を調べます。
一旦TCP接続のために作ったコンテナを使って確認します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# dockerコンテナの中に入る。
docker exec -it myql_tcp /bin/bash
# ここからコンテナの中
# mysql.sockの位置を調べる。
mysql -u root -p
# =>任意のパスワードを入力
show variables like '%sock%'
+-----------------------------------------+-----------------------------+
| Variable_name | Value |
+-----------------------------------------+-----------------------------+
| mysqlx_socket | /var/run/mysqld/mysqlx.sock |
| performance_schema_max_socket_classes | 10 |
| performance_schema_max_socket_instances | -1 |
| socket | /var/run/mysqld/mysqld.sock |
+-----------------------------------------+-----------------------------+

# mysql終了
quit;

# dockerコンテナから出る
Ctrl+p,Ctrl+q

mysql.sockは、mysqlコンテナ上でmysqld.sockという名称だと確認できました。
パスは/var/run/mysqld/mysqld.sockなので、/var/run/mysqldディレクトリをローカルにマウントさせればよさそうです。

以下のコマンドで、コンテナを作成と起動します。

1
2
3
4
5
6
7
8
9
10
# コンテナの作成
# -v /tmp:/var/run/mysqld
# コンテナ上の/var/run/mysqldをローカルマシンの/tmpに展開する
#
# -e MYSQL_ROOT_PASSWORD=[任意のパスワード]
# パスワード設定
docker create --name mysql_sock -v /tmp:/var/run/mysqld -e MYSQL_ROOT_PASSWORD=[任意のパスワード] mysql

# コンテナの開始
docker start mysql_sock

ここで、/tmpを確認すると、mysqld.sock他があることを確認できます。
docker stop mysql_sockすると、mysqld.sock他が消えます。

ここでUNIXドメインソケット用の設定をconfig/database.ymlに以下の通り入力する。

config/database.yml(development抜粋)
1
2
3
4
5
6
7
8
9
10
11
default: &defalt
adapter: mysql2
pool: <%= ENV.fetch("RAILS_MAX_THREADS")%>
timeout: 5000
encoding: utf8

development:
database: mysql_developmentDB
username: [任意のID]
password: [任意のパスワード]
socket: /tmp/mysqld.sock #mysqld.sockになっていることを確認

以下の通り、入力してrailsアプリを起動します。

1
2
3
4
5
# DB作成=>失敗
bundle exec rails db:create

# Railsアプリの開始=>失敗
bundle exec rails s

ここまでやってみましたが、.sockファイルをローカルにマウントさせる方法はできませんでした。
うーん残念。

どうにも納得できなくて、再度UNIXドメインソケットについて調べ直しました。
「単一オペレーションシステム内で~」というのが見落としポイントでした。
確かにMySQLはコンテナ上に立ち上がっているので、確かに単一オペレーションシステム内ではないです。
だから、.sockファイルをローカル側から見えるようにしてもダメでした。
この点については納得しました。


番外:docker上のMySQLにローカルから直接接続

TCP接続用のMySQLコンテナに、ローカルのmysqlクライアントで接続できます。
一々コンテナの中に入ってmysqlクライアントを起動するよりも楽です。

1
2
3
mysql -u root -p -h 127.0.0.1 --protocol=TCP
# mysql -u root -p --protocol=TCP でもOK
=>パスワード入力

今回はRails開発環境用にMySQLをDockerで用意してみました。
結果としてUNIXドメインソケットを学ぶきっかけになったのがよかったです。
今後はケースバイケースで、dockerでDBの用意します。

ではでは。