LoginSignup
4
2

More than 1 year has passed since last update.

フルスタックエンジニアへの道 part 2 ~Rails 7 × Dockerの環境構築 2

Posted at

前回: 個人開発をやる目的とか、何をするかなどはこちらから

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!!!!!!!

スクリーンショット 2022-05-25 1.12.20.png

これで、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アドレスを固定させるのか?

https://qiita.com/takara@github/items/2349fff473474d7fcf47

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2