【備忘録】VirtualBoxのAlmaLinuxサーバーに構築したMySQLと、ローカルのDockerコンテナを接続する

## はじめに
VirtualBoxのAlmaLinuxサーバーに構築したMySQLと、ローカルのDockerコンテナを接続する手順の備忘録です。

**環境**：Mac M3

**前提**: 
VirtualBoxのAlmaLinuxサーバーにMySQLをインストールしている

https://qiita.com/yuzu_ponz007/items/9235faf35f03e20e33df

## やってみよう
以下の手順で進めます

1. ローカルにDockerfileなどを準備
2. VirtualBoxを起動しMySQLにrootユーザでログインし一般ユーザを作成する
3. MySQLテーブルの初期設定
4. ローカルでMySQLに接続するための情報を書く
5. Dockerコンテナを起動しlocalhost:5001 にアクセス

## 1.ローカルにDockerfileなどを準備

任意のフォルダに下記のシェルスクリプトを作成
```ruby:test.sh
#!/bin/bash

# Flaskアプリ用ディレクトリ作成
mkdir -p flask-app/templates
cd flask-app || exit

# Dockerfile作成
cat <<EOF > Dockerfile
FROM python:3.9-slim

WORKDIR /app

RUN apt-get update && apt-get install -y \\
    build-essential \\
    && apt-get clean \\
    && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY . .

ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0

EXPOSE 5000

CMD ["flask", "run"]
EOF

# docker-compose.yml作成
cat <<EOF > docker-compose.yml
version: '3'

services:
  web:
    build: .
    ports:
      - "5001:5000"
    environment:
      - FLASK_ENV=development
EOF

# requirements.txt作成
cat <<EOF > requirements.txt
Flask==2.3.2
mysql-connector-python==8.0.33
EOF

# app.py作成
cat <<EOF > app.py
from flask import Flask, render_template, request, redirect
import mysql.connector

app = Flask(__name__)

def get_db_connection():
    return mysql.connector.connect(
        host='YOUR_MYSQL_HOST',
        user='YOUR_USER',
        password='YOUR_PASSWORD',
        database='flask_db'
    )

@app.route('/')
def home():
    connection = get_db_connection()
    cursor = connection.cursor()
    cursor.execute("SELECT message FROM greetings")
    messages = cursor.fetchall()
    cursor.close()
    connection.close()
    return render_template('index.html', messages=messages)

@app.route('/add', methods=['POST'])
def add_message():
    message = request.form['message']
    connection = get_db_connection()
    cursor = connection.cursor()
    cursor.execute("INSERT INTO greetings (message) VALUES (%s)", (message,))
    connection.commit()
    cursor.close()
    connection.close()
    return redirect('/')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
EOF

# templates/index.html作成
cat <<EOF > templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>今日もお疲れ様！！</title>
</head>
<body>
    <h1>今日は金曜日！明日から夢の週末ですね！</h1>
    <form action="/add" method="post">
        <input type="text" name="message" placeholder="Enter your message" required>
        <button type="submit">Add Message</button>
    </form>
    <h2>Messages:</h2>
    <ul>
        {% for message in messages %}
        <li>{{ message[0] }}</li>
        {% endfor %}
    </ul>
</body>
</html>
EOF

echo "Flaskアプリ用のファイル群を作成しました。"
```
```ruby:実行権限がない場合
chmod +x test.sh
```

```ruby:スクリプトを実行
./test.sh
```

## 2. VirtualBoxを起動しMySQLにrootユーザでログインし一般ユーザを作成する
```ruby:MySQLにrootユーザでログイン
mysql -u root -p
```
```ruby:ユーザー作成と権限付与
CREATE USER 'ユーザ名'@'%' IDENTIFIED BY 'パスワード';
GRANT ALL PRIVILEGES ON flask_db.* TO 'ユーザ名'@'%';
FLUSH PRIVILEGES;
```

## 3.MySQLテーブルの初期設定
```ruby:データベース作成
CREATE DATABASE flask_db;
```
```ruby:テーブル作成
USE flask_db;
CREATE TABLE greetings (
    id INT AUTO_INCREMENT PRIMARY KEY,
    message VARCHAR(255) NOT NULL
);
```

## 4. ローカルにFlask側でMySQL接続設定
```ruby:app.py
def get_db_connection():
    return mysql.connector.connect(
        host='AlmaLinuxサーバーのIPアドレス（ip aコマンドで確認できる）',
        user='MySQL一般ユーザ名',
        password='MySQL一般ユーザのパスワード',
        database='flask_db'
    )
```

## 5. Dockerコンテナを起動し localhost:5001 にアクセス
flask-appで下記コマンド実行
```ruby:Dockerコンテナを起動
docker compose up -d
```
または
```ruby:Dockerコンテナを起動
docker compose up --build
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/e724407e-26eb-4188-974f-882491f505c1.png)


## 参考文献

https://qiita.com/free-honda/items/b8e9e483b4836117cbd0