DockerでMySQLのサーバーを立てる

# はじめに
DockerでMySQLのサーバを立てるとき、調べたことを記載します。


### フォルダ構成
```フォルダ構成. 
Docker
├mysql
│　├DB
│　│　└sqlファイル
│　└Dockerfile
│　└my.cnf
└docker-compose.yml
```

### dockerfile
```dockerfile.
FROM mysql:8.0

EXPOSE 3306

ENV MYSQL_DATABASE cafekatu_db

ADD my.cnf /etc/mysql/conf.d/my.cnf

COPY db /docker-entrypoint-initdb.d

CMD ["mysqld"]
```

1行目　ベースをダウンロード
2行目 ポートを開ける
3行目 環境変数を設定
4行目　MySQL設定ファイルをイメージ内にコピー
5行目　sqlをコピー
6行目　docker runに実行される

### mysql設定ファイル
```my.cnf
[mysqld]
character-set-server=utf8

[mysql]
default-character-set=utf8

[client]
default-character-set=utf8
```

MySQLの文字コードの設定する。

### 初期データ
```00_database.sql
CREATE DATABASE IF NOT EXISTS cafekatu_db;
```

```01_table.sql
CREATE TABLE IF NOT EXISTS cafes (
    id             INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name          VARCHAR(255) NOT NULL,
    prefecture_id        INT NOT NULL,
    city     VARCHAR(255) NOT NULL,
    street     VARCHAR(255),
    business_hours     VARCHAR(255) NOT NULL,
    approved        INT NOT NULL DEFAULT 0,
    deleted        INT NOT NULL DEFAULT 0,
    created_at      TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp,
    updated_at     TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp
)
```

```02_insert.sql
INSERT INTO cafes (name, prefecture_id,city,street,business_hours) VALUES ('お菓子の家', 1,'中央区','銀座','11時から15時まで');
INSERT INTO cafes (name, prefecture_id,city,street,business_hours) VALUES ('coffee shop', 1,'新宿区','歌舞伎町','8時から12時まで');
INSERT INTO cafes (name, prefecture_id,city,street,business_hours) VALUES ('お菓子の家', 1,'渋谷区','渋谷','毎週土曜日定休日');
```


Dockerfile参考
[Docker + MySQLで開発環境用DBの作成](https://mmtomitomimm.blogspot.com/2018/04/docker-mysqldb.html)
[DockerでMySQLを使ってみる](https://qiita.com/TAMIYAN/items/ed9ec892d91e5af962c6)
[Go言語で基本的なCRUD操作を行うREST APIを作成](https://dev.classmethod.jp/articles/go-sample-rest-api/)


# 改善 Dockerfileとdocker-composeの設定
### dockerfile
```dockerfile.
FROM mysql:8.0

EXPOSE 3306

COPY my.cnf /etc/mysql/conf.d/my.cnf

RUN env

CMD ["mysqld"]
```

### docker-compose
```docker-compose.
cafekatu_db:
    image: cafekatu_db
    container_name: cafekatu_db
    build: 
        context: ./dockerfile/mysql
        dockerfile: ./Dockerfile
    volumes:
      - ./dockerfile/mysql/db:/docker-entrypoint-initdb.d  #初期データ
    environment:
      MYSQL_ROOT_PASSWORD: ****
      MYSQL_DATABASE: cafekatu_db
      TZ: "UTC"
    ports:
      - "127.0.0.1:3307:3306"
```

## 改善点
データの初期値はdocker-compose側でVolume Mountするのが一般的

```
volumes:
      - ./dockerfile/mysql/db:/docker-entrypoint-initdb.d
```

## docker volumeって何
dockerのコンテナで作成したデータを永続化するもの
コンテナを破壊してもボリュームに保存されたデータは破壊されない

>ボリュームドライバーを用いると、リモートホスト上、あるいはクラウドプロバイダー上のボリュームに保存できるようになる。 
ボリューム内のデータは、コンテナーのライフサイクルから離れたところに存在している

[dockerk　公式リファレンス](https://matsuand.github.io/docs.docker.jp.onthefly/storage/volumes/)


docker run をするときに
-v [volume名]:[コンテナのvolume用ディレクトリ]
のオプションでvolumeを指定できる。
ボリュームはホスト側に作成される。Dockerの管理下でストレージ領域を確保する。


>volumeがDocker上に作成される記憶領域です。
bind(バインドマウント)がホスト側のディレクトリとコンテナのディレクトリをマウントさせる機能です。
[Dockerでvolumesを設定する](https://zenn.dev/ajapa/articles/fc1205d4bcbfe7)


[Docker の Volume がよくわからないから調べた](https://qiita.com/aki_55p/items/63c47214cab7bcb027e0)

docker-compose.ymlのservice内でvolumeを規定する場合、
```
volumes:
      - [ホスト側の相対Path]:コンテナの絶対Path
```
という形で設定する。
[docker-composeでvolumesを設定する](https://zenn.dev/ajapa/articles/1369a3c0e8085d)

[Docker 上で MySQL データを永続化する](https://kiyobl.com/docker-mysql-persistence/)

## /docker-entrypoint-initdb.dとは

>docker の MySQL image では /docker-entrypoint-initdb.d/ というディレクトリ内に初期化用のSQLやスクリプトを置くことで、最初に image を起動したときにデータの初期化を自動的に行う仕組みがあります。
[Docker で MySQL 起動時にデータの初期化を行う](https://qiita.com/moaikids/items/f7c0db2c98425094ef10)