Dockerを使って、DjangoからMySQLにアクセスしてみた

# はじめに
Dockerコンテナ上に建てたMySQLをDjangoでマイグレーションして、テーブル操作を実施します。
実行環境は以下です。これらが全て正常にインストールされていることを前提とします。

| 対象 | 環境 |
|:-:|:-:|
| OS| Windows10  |
| PG | Python 3.12.6 |
| MW | Docker Desktop 27.1.1 |

# 1. DockerでMySQLを構築する
DockerHubからMySQLコンテナイメージの最新バージョンを取得します。
https://hub.docker.com/

## ①検索ボックスからMySQLを検索
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665882/4666c37a-f17b-4abb-3b60-8b8470314c20.png)

## ②プルコマンドをコピー
「Docker Official Image」のMySQLを開き、右部にあるプルコマンドをコピーする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665882/440a661e-3921-2c4a-2573-2dd82409c583.png)

## ③ターミナル上でプルコマンド実行
VSCodeで作成したプロジェクトからターミナルを開き、先ほどコピーしたプルコマンドを実行します。
以下の表示が出れば、MySQLイメージのプル成功です！
正常にダウンロードされているかを確認したい場合は、「__docker images__」コマンドを実行してダウンロード済みのイメージファイルを確認してください。

```PowerShell:
PS D:\User\Django_work> docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
5e407bf3af90: Pull complete
5f79c432ce4c: Pull complete
e93edcbaa54f: Pull complete
a0535a79ba39: Pull complete
20ab03fc7bed: Pull complete
75f2fdac1421: Pull complete
f8d6a5d16572: Pull complete
b8dff4a91460: Pull complete
90c257e20398: Pull complete
17219240cf71: Pull complete
Digest: sha256:c69299937e5e2fc9a2cb26f5cd7a7151e48d9d5a3b3679f62bfd1275de698c0c
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest

What's next:
    View a summary of image vulnerabilities and recommendations → docker scout quickview mysql
```

## ④コンテナを作成して起動
Docker上にMySQLコンテナを作成して起動します。
実行するためのコマンドは、先ほどアクセスしたDockerHub上にHowToで情報がありますので、他のイメージでも同様に確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665882/a1473863-4e28-3c39-a030-5a09f8158851.png)

~~~PowerShell:
docker run --name Tea-mysql -p 13306:3306 -e MYSQL_ROOT_PASSWORD=TeaDj4ngoW0rk -d mysql
~~~
| オプション | 内容 |
|:-:|:-:|
| --name |  コンテナ名 |
| -p|  ポートフォワディング指定　<ローカルポート>：<コンテナ側ポート>|
| -e | 環境変数 |
| -d | デタッチドモード指定 |

正常終了すると、Dockerコンテナが作成されて起動します。
実行結果を確認する場合は、「__docker ps__」コマンドを実行してください。

~~~PowerShell:
PS D:\User\Django_work> docker ps
CONTAINER ID   IMAGE     COMMAND                   CREATED          STATUS          PORTS                                NAMES
dc32dfcf11d3   mysql     "docker-entrypoint.s…"   56 seconds ago   Up 55 seconds   33060/tcp, 0.0.0.0:13306->3306/tcp   Tea-mysql
~~~

## ⑤DockerからMySQLにアクセス
「__docker exec__」コマンドを実行して、bashでコンテナにアクセスします。
bashが開いたら、「__mysql -u root -p__」を実行し、環境変数に指定したパスワードを入力するとMySQLに接続への出来ます。

~~~powershell:
PS D:\User\Django_work> docker exec -it Tea-mysql bash

bash-5.1# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 9.0.1 MySQL Community Server - GPL

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
~~~

## ⑥MySQL上にユーザ用データベースを作成する
mysql上に、以下のSQLを実行してデータベースを作成してください。

~~~Powershell:
mysql> CREATE DATABASE TEST;
Query OK, 1 row affected (0.02 sec)

mysql> show DATABASES;
| Database           |
| TEST               |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)
~~~

# 2. Djangoプロジェクトを構築する
Docker上にMySQLが起動出来たら、次はDjangoプロジェクトを構築していきます。
テンプレートやurls等を全て乗せると長くなりますので、実際のソースはGitHub上からプルしてください。
ここでは環境構築と実装の流れについて解説します。

## ①venvで仮想環境を設定
プロジェクトフォルダをVSCodeで開き、以下のコマンドを実行します。

~~~powershell:
python -m venv <仮想環境名>
~~~

正常終了すると、フォルダ内に仮想環境フォルダが作成されますので、以下のコマンドを実行して仮想環境をアクティベートします。

~~~powershell:
PS D:\User\Django_work\DjangoApp> .\.venv\Scripts\activate
(.venv) PS D:\User\Django_work\DjangoApp> pip list
Package Version
------- -------
pip     24.2
(.venv) PS D:\User\Django_work\DjangoApp> 
~~~
:::note warn
Powershellだと権限の問題でコマンドが失敗する可能性がありますので、エラーが出た場合は以下を試してみてください。
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
:::


## ②Djangoをインストールする
仮想環境が実行出来たら、次はDjangoをインストールします。
他環境に影響を与えないため、venvがアクティベートされている状態で実行してください。
「__pip install Django__」コマンドを実行します。

~~~powershell:
(.venv) PS D:\User\Django_work\DjangoApp> pip list
Package Version
------- -------
pip     24.2
(.venv) PS D:\User\09_Work\Django_work\DjangoApp> pip install Django
Collecting Django
  Downloading Django-5.1.1-py3-none-any.whl.metadata (4.2 kB)
Collecting asgiref<4,>=3.8.1 (from Django)
  Using cached asgiref-3.8.1-py3-none-any.whl.metadata (9.3 kB)
Collecting sqlparse>=0.3.1 (from Django)
  Using cached sqlparse-0.5.1-py3-none-any.whl.metadata (3.9 kB)
Collecting tzdata (from Django)
  Using cached tzdata-2024.1-py2.py3-none-any.whl.metadata (1.4 kB)
Downloading Django-5.1.1-py3-none-any.whl (8.2 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.2/8.2 MB 13.1 MB/s eta 0:00:00
Using cached asgiref-3.8.1-py3-none-any.whl (23 kB)
Using cached sqlparse-0.5.1-py3-none-any.whl (44 kB)
Using cached tzdata-2024.1-py2.py3-none-any.whl (345 kB)
Installing collected packages: tzdata, sqlparse, asgiref, Django
Successfully installed Django-5.1.1 asgiref-3.8.1 sqlparse-0.5.1 tzdata-2024.1
(.venv) PS D:\User\Django_work\DjangoApp> pip list
Package  Version
-------- -------
asgiref  3.8.1
Django   5.1.1
pip      24.2
sqlparse 0.5.1
tzdata   2024.1
~~~

## ③Djangoプロジェクトを作成
仮想環境上にDjangoがインストール出来たら、構築するDjangoプロジェクトを作成していきます。
「__django-admin startproject <プロジェクト名>__」を実行してください。

成功すると、エクスプローラ上にアプリケーションが作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665882/6b4d9374-2fe2-0413-2696-c89758760bf9.png)

## ④アプリケーションを作成
Djangoプロジェクトを作成したら、次はアプリケーションを作成します。
「__python manage.py startapp <アプリ名>__」を実行して、プロジェクト内にアプリケーションフォルダが作成されることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665882/b0ce7660-f485-7748-ec8a-785458a241d3.png)

## ⑤Pythonファイルの設定
僕の方で、テスト用のプロジェクトをGitHub上に公開しましたので、こちらを利用してマイグレーションを実施してみてください。

https://github.com/Madoyume/Django_work

ここでは、MySQLにアクセスするための重要な設定を記述します。

~~~python:setting.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME':  'Tea-mysql',
        'USER': 'root',
        'PASSWORD': 'TeaDj4ngoW0rk',
        'HOST': 'localhost',
        'PORT': '13306',
    }
}
~~~

~~~python:models.py
from django.db import models

class Test1(models.Model):
    name = models.CharField(max_length=100)
    mail = models.EmailField(max_length=200)
    gender = models.BooleanField()
    age = models.IntegerField(default=0)
    birthday = models.DateField()
    
    def __str__(self):
        return f'<Test1:id={str(self.id)}, {self.name}({self.age})>'
~~~

~~~python:admin.py
from django.contrib import admin
from .models import Test1

admin.site.register(Test1)
~~~

## ⑥mysqlclientをインストール
「__pip install mysqlclient__」コマンドを実行して、仮想環境上にMySQL用のクライアントライブラリをインストールします。


## ⑦マイグレーションを実行
ここまで来ればあと一息です。
「__python manage.py makemigrations <アプリ名>__」及び、「__python manage.py migrate__」を実行して、結果が以下のように実行されればマイグレーション成功です！

~~~powershell:
(.venv) PS D:\User\Django_work\DjangoApp\Django_App> python manage.py makemigrations test
No changes detected in app 'test'
(.venv) PS D:\User\Django_work\DjangoApp\Django_App> python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, test
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK
  Applying test.0001_initial... OK
~~~

# 3. adminでデータを作成して、画面上で確認
せっかくなので、画面からデータの作成、抽出が出来るか確認してみましょう。

## ①管理ユーザを作成する
ターミナルから以下のコマンドを実行して、管理用ユーザを作成してください。

~~~powershell:
python manage.py createsuperuser
~~~
ユーザ名、メールアドレス、パスワードを聞かれるので、任意の情報を入力して操作を完了してください。

## ②Djangoサーバを実行する
「__python manage.py runserver__」コマンドを実行してサーバを起動してください。

## ③管理用画面を開き、データを作成する
ブラウザ上で「__htt p://127.0.0.1:8000/admin__ 」を開くと、以下の画面が開きます。
先ほど作成した管理ユーザの情報を入力して、Log inを押してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665882/2dd63d28-2967-3162-3961-a3a50e6ffe93.png)

ログインすると、以下の画面が開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665882/6d2120a2-7d30-fba1-13df-f9dabf049071.png)

テーブルの「Add」を押下して、作成するデータを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665882/ff94f0a8-8aa9-89b5-6c27-7b8b0fd04a7d.png)

## ④Djangoアプリ画面を開き、結果を確認する
ブラウザ上で「__htt p://127.0.0.1:8000/test__ 」を開き、先ほど作成したデータが表示されていれば無事完了です。お疲れさまでした！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665882/be30da9b-378b-9b8c-5919-7ded45668c61.png)

# 参考文献
__Pythonプログラミング VTuber サプー__ 様
【Docker入門】初心者向け！Dockerの基本を学んでコンテナ型の仮想環境を作ろう！
https://youtu.be/B5tSZr_QqXw?si=tKlrCpidQ3ZhDx9O

__掌田津耶乃__ 様
PythonDjango4 超入門
https://amzn.asia/d/cVl9GTe