Vagrant仮想環境に入れたMySQLに、ローカルSpringBootから接続する方法

#はじめに
仮想環境にMySQL設置してローカルからつなぐ手順の備忘録です。
今お手伝いさせて頂いているプロジェクトではSpringBootを使い、Thymeleaf + JavaでMVC構造を作り、MySQLを仮想環境において接続する必要があったのですが、
MySQLのバージョンが5.6から5.7に変わった事、provisionで手順を短縮させたい事から構築に時間がかかってしまったので書きました。
ビルドツールはGradleを使用しています。

#環境
#####ローカル
Vagrant 2.2.7
Virtualbox 6.1.6
SpringBoot 2.2.6
Gradle 6.4.1

#####仮想環境
centos 7.2
MySQL 5.7

#手順

1.vagrantfile作成
2.provisionファイル作成
3.SpringBoot設定ファイル修正
4.接続確認

### 1.Vagrantfile作成

```file:Vagrantfile
Vagrant.configure("2") do |config|

  config.vm.box = "bento/centos-7.2"
  config.vm.box_version = "2.3.1"

  config.vm.box_check_update = false
  config.ssh.insert_key = false

　#ポートフォワードの設定、[host: 8080]はSpringBootと被ったので今回はこちらを修正
  config.vm.network "forwarded_port", guest: 80, host: 10080

　#仮想環境にアクセスするIPアドレスを設定、後でSpringBootの設定をする際にこのIPアドレスを使う。
  config.vm.network "private_network", ip: "192.168.33.10"

　#仮想環境とローカルの共有フォルダを設定
  config.vm.synced_folder "..", "/home/vagrant/{project_name}",
    create: true, owner: "vagrant", group: "vagrant"

  config.vm.provider "virtualbox" do |vb|
     vb.memory = "2048"
  end

# vagrant up 実行時にprovisionするように設定
  config.vm.provision :shell, :path => "provision.sh"
end
```
### 2.provisionファイル作成
```sh:provision.sh
echo "<<< provision start >>>"

echo "<<<MySQLインストール>>>"
sudo yum localinstall -y http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
sudo yum info mysql-community-server
sudo yum install -y mysql-community-server

#root@localhostに自動でパスワードを割り当てられないように設定
sudo mysqld --initialize-insecure --user=mysql

echo "<<<mysqld起動>>>"
sudo service mysqld start
sudo service mysqld status

echo "<<<SQLコマンド>>>"
mysql -u root < /vagrant/files/migrate.sql
mysql -u root < /vagrant/files/grant.sql
sudo systemctl enable mysqld.service

echo "<<< provision finish >>>"
echo "<<< Access to http://localhost:8080/ from your HostPC >>>"
```
MySQLはバージョン5.7以降からrootアカウントの仮パスワードが自動生成されるようになったので、そのままSQLに接続しようとすると「パスワードがちがうぞ」とエラーが吐かれるので、初期起動の前にmysqld --initialize-insecureで初期化する必要があった


```sql:migrate.sql
-- NO_AUTO_CREATE_USERを消す事で、存在しないユーザーにGRANT文を発行した場合自動的に新規ユーザーを作成しGRANT文が発行されるように設定
SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
CREATE DATABASE {project_name} CHARACTER SET utf8;
```

一度、SET GLOBAL sql_modeの内容を反映させる必要があるので、grantコマンドは別ファイルに作成。

```sql:grant.sql
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
```

### 3.SpringBoot設定ファイル修正
```gradle:build.gradle
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-jdbc'
    compile 'mysql:mysql-connector-java:5.1.35'
}
```
```properties:application.properties
spring.datasource.url=jdbc:mysql://192.168.33.10:3306/{project_name}
spring.datasource.username=root
#spring.datasource.password=#パスワード、現状は空で設定
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#クラスパス直下のSQLファイルが存在すれば読み込んで実行されるように設定
spring.datasource.initialization-mode=always
```

```sql:schema.sql
CREATE TABLE IF NOT EXISTS item (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  name varchar(255),
  price real,
  vendor varchar(255),
  PRIMARY KEY (id)
);
```
schema.sqlはapplication.propertiesと同じresources直下に保存。今回は接続が確認できればいいので適当な内容で作成。

### 4.接続確認

application.propertiesの設定からアプリケーション起動時にtableがなければ自動的に作成されるようにしているので。
プロジェクトのvagrantフォルダ直下に移動し「vagrant up」後にIDEやビルドツールでアプリケーション起動すれば接続が完了しています。

今回はビルドツールはGradleを使用しているので

```
gradle bootRun
```

ssh接続して、mysql -u rootでパスワードなしで入れるようにしているので

```sql:mysql
use {database名};
show tables;
```
で起動時に自動生成されたテーブルが確認できます。



#参考サイト
https://qiita.com/norifumi92/items/60a23090a7172e65954d
https://yoku0825.blogspot.com/2018/10/mysql1133erpasswordnomatch-cant-find.html
https://gihyo.jp/dev/serial/01/mysql-road-construction-news/0010
https://www.qoosky.io/techs/7ca8f6c2b1