前回: 個人開発をやる目的とか、何をするかなどはこちらから
https://qiita.com/Terao-Takumi/items/f33393f7e99d40d7e4bb
今回のゴール: Docker上に起動したMySQLとRailsを接続し、rails sする。
dockerまわりの設定
Dockerfile: 最後にこれを足す
$ CMD ["mysqld"] # mysqlを起動
docker-compose.yml
db-sloth:
image: mysql:5.7
platform: linux/x86_64 # M1 Macだと動かないのでplatformを指定
volumes:
- ./db/development/tools:/docker-entrypoint-initdb.d # 初回データ実行
- ./db/development/db:/var/lib/mysql # データ永続化
environment:
MYSQL_ROOT_PASSWORD: root
TZ: Asia/Tokyo
hostname: db-sloth
ports:
- "3306:3306"
command: mysqld --sql_mode="NO_ENGINE_SUBSTITUTION" --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --innodb-flush-log-at-trx-commit=0 --default-authentication-plugin=mysql_native_password --innodb-ft-enable-stopword=0
networks:
- shared-network
だいたいこの記事に書いてくださっているので、これ読めばわかります(笑)
https://qiita.com/leafeon00000/items/e190cf92af3a487cc749
ここで重要なのが、volumeという概念。これは、コンテナを削除したとしてもデータが残り続けるもの。
参考:
https://zenn.dev/ajapa/articles/fc1205d4bcbfe7
今回は、、、
./db/development/tools:/docker-entrypoint-initdb.d
これで:
の左のディレクトリ配下のファイル(ローカルファイル)を右のディレクトリ配下(docker側ファイル)にマウントするということを記述している。1つめのこれは、
docker-entrypoint-initdb.d ディレクトリにsqlファイルを入れておくことで、コンテナ作成時にsqlを実行してDBとかテーブルを初期セットしておくというギミック。
- ./db/development/db:/var/lib/mysql # データ永続化
これは、mysqlのデータをずっと残しておくためにdb/development/db 配下においておくよ~ということ。コマンドは、なんか、魔法です(笑)。色々設定をここで変更している感じ。
initialize_db.sql
DROP DATABASE IF EXISTS sloth;
CREATE DATABASE sloth;
USE sloth;
DROP TABLE IF EXISTS `memo`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `memo`
(
`memo_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'メモID',
`memo_title` varchar(255) NOT NULL COMMENT 'メモタイトル',
`memo_content` text COMMENT 'メモ内容',
PRIMARY KEY (`memo_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
くっそかんたんなメモテーブルだけを入れておいた。スピーディーにRails sするため、ここは手を抜こう…。後からテーブル追加したり、ガンガンalter tableしていく。テーブル変更を恐れない。それがアジャイル。
注意点は、先にローカルでdb作っていたり、間違えて変なファイルができてしまったりしたときに、docker-entrypoint-init.d配下のsqlだったりshだったりが起動しないということ(これに気づかず1時間くらい格闘していた)
https://zenn.dev/re24_1986/articles/978801ae092498
実行スクリプト作成での補足
docker-entrypoint-initdb.d 内に複数のスクリプトが存在する場合、名前順で実行
実行タイミングは、/var/lib/mysqlがない場合に実行される
database.ymlの編集
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: root
host: db-sloth # docker-compose.ymlで設定した名前
development:
<<: *default
port: 3306
database: sloth
ま、ポート番号あわせて、host-name合わせることくらい。何も難しいことはない。
docker composeして確認
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dac9ad924d5f sloth-web_web-sloth "entrypoint.sh tail …" 22 seconds ago Up 20 seconds 0.0.0.0:3002->3002/tcp sloth-web_web-sloth_1
b74377851690 mysql:5.7 "docker-entrypoint.s…" 22 seconds ago Up 21 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp sloth-web_db-sloth_1
4ee6c1526f2f redis:6.2-alpine "docker-entrypoint.s…" 22 seconds ago Up 21 seconds 0.0.0.0:6382->6379/tcp sloth-web_redis-sloth_1
→無事 image = mysql:5.7 のコンテナができていて、、、
mysql入って…
$ docker exec -it 6b1d61e42d35 bash
$ mysql -uroot -proot # -uはユーザー、-pはパスワードを予め入力できるオプション
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sloth |
| sys |
+--------------------+
5 rows in set (0.01 sec)
→できてる。
いざ、、、
Rails s!!!!!!!
これで、Rials 7 × Docker × MySQLの環境構築が無事できましたとさ。
次回はメモ帳のUIを作っていこうかしら。ひとまずXDでデザインこしらえて、vue.jsとか使ってSPAを実装してみたい。
補遺: shared-networkについて
ちょっと物足りないので、今回docker-composeでコンテナのネットワークにshared-networkを使ったのを少しだけ解説したい。
Shared-networkとは?
docker-compose.ymlで定義された複数の環境間で通信を行うことができるネットワーク環境のこと。今回使う必要性はまったくないが、やってみたかったのでやってみたという経緯。
例えば、
・アプリケーション A
・アプリケーション B
・それを紐付けるAPI
と3つのプロジェクトがあったときに、それらを全部つなげたい…ってな場合に便利なんじゃないかと思われる。社内システムとか作っているとよくあることなのかな?
デフォルト設定ではどうなる?
dockerを実行状態にしておくと、3つのnetworkが立ち上がっている。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
997b7bca7af9 bridge bridge local
eda438fe48a8 host host local
3548002f655e none null local
そこから(一般的な方法で)docker-composeをすると、、、
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
997b7bca7af9 bridge bridge local
eda438fe48a8 host host local
3548002f655e none null local
82cded1a198f sloth-web_app_net bridge local
sloth-web_app_netが増える。これは、docker-composeのnetworksで
networks:
app_net: # ネットワークの名前
driver: bridge
ipam: # IP Address Management
driver: default
config:
- subnet: 172.20.101.0/24 # 0~24までの幅で使うと言っておく
こんなふうに定義されている。そして、作られたネットワークの中身を見てみると、、、
$ docker inspect [ネットワークID]
[
{
"Name": "sloth-web_app_net",
"Id": ここにID,
"Created": "2022-05-23T05:28:59.372943095Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.20.101.0/24"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"28012fe2c27a1c9293d13f5470a3d1161f021b48db0f940eb51709f324ef39f0": {
"Name": "コンテナの名前1",
"EndpointID": "cc4016f7f64dcab24053248e0e97b902f569c82a72b62acc48087ee673c63aa3",
"MacAddress": "02:42:ac:14:65:04",
"IPv4Address": "172.20.101.4/24",
"IPv6Address": ""
},
"2cb70ccca32edc27ba31343abfc6c85e918441abf1075b3aa05ac7474a4e1435": {
"Name": "コンテナの名前2",
"EndpointID": "5bb65c62eb476d2c60c5785ed90034fc64ffd1e5e7de130ac233f2dc4b8e3443",
"MacAddress": "02:42:ac:14:65:03",
"IPv4Address": "172.20.101.3/24",
"IPv6Address": ""
},
"f093c59b62c5e151071bdcf2a40d81e1d4f15b0d9ce196e341b3215a3822bc8c": {
"Name": "コンテナの名前3",
"EndpointID": "4b9c39201f21e22f632b545aac52da5b9d59b2ed4cdff87013e837470abe5bba",
"MacAddress": "02:42:ac:14:65:02",
"IPv4Address": "172.20.101.2/24",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "app_net",
"com.docker.compose.project": "sloth-web",
"com.docker.compose.version": "1.29.2"
}
}
]
つまり、app_netという名前のネットワークに3つのコンテナが紐付いていて、それぞれのコンテナ間で通信が可能になっている。
なぜデフォルトのネットワークではなく、自前のネットワークを使うのか?
→多分、IPアドレスを固定したいから。だが、なぜ固定させたいのかがまだきちんとわかっていない。IPアドレスが変わったらめんどくさい環境設定がどこかにあるはず…。
参考記事: 複数のdocker-compose間で通信する
https://tech.anti-pattern.co.jp/docker-compose/
参考: 参考訳:Docker コンテナ・ネットワークの理解
https://qiita.com/zembutsu/items/1da05cb6a60e1c5acc25
参考: networksキー
https://docs.docker.jp/compose/networking.html
参考: なぜIPアドレスを固定させるのか?