【初心者向け】Python仮想環境のDjangoとdockerコンテナのMySQLとの接続

Djangoアプリはデフォルトでsqlite3が使えるように設定されていますが、MySQLに変更したい場合があります。ホスト環境で動作しているMySQL(v8.0.41)との接続から検証します。設定変更は簡単ですが、専用のドライバーをインストールする必要があります。まずはここを押さえておいて、Dockerコンテナで起動しているMySQLと接続する場合を考えます。

Dockerコンテナにはバージョンの異なる2種類があったとします。今の開発環境ではどちらにも接続できるのか、どちらかにしか接続できないのか、ホスト側の接続方法との違いはあるのかなど、知っておかないと無駄に時間を費やすことになります。

ここではDjangoプロジェクトは全てPythonの仮想環境上で開発しているものとし、データベースのみを切り替える場合についてメモします。

検証環境

  • OS : Ubuntu 22.04
  • MySQL(Host) : v8.0.41
  • MySQL (Docker) : v5.7 / v8.0

検証模式図

Djangoの設定

まずは仮想環境に入って、何も考えず最新のDjangoをインストールします。

pip install django

pip freeze
  asgiref==3.8.1
  Django==5.1.6      # ⬅これを使用する
  sqlparse==0.5.3
  typing_extensions==4.12.2

django-admin startproject <project_name>コマンドでprojectの作成と、python manage.py startapp <app_name>コマンドでアプリの作成、それとtemplatesフォルダの作成と、settings.pyの基本設定を行ってから、python manage.py runserver でサーバーが起動されることをURL:"localhost:8000"で確認します。

ホスト側のMySQLと接続

  1. settings.pyでデータベースをデフォルトのsqlite3からmysqlに変更します。
    MySQLに切り替えるときは事前にデータベース側の設定は終えておいてください。

settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_db', 
        'USER': 'django_user',
        'PASSWORD': 'django_pass',
        'HOST': 'localhost',
         'PORT': '3306', 
    }
}
  1. 初期設定のまま、サーバー起動しようとしてもできません。
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?

ここでmysqlclientをインストールします。

pip install mysqlclient

 #....中略....
  Getting requirements to build wheel did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

しかしエラーが発生しました。Djangoアプリケーションが別のプロセス(サブプロセス)を起動した際に、そのサブプロセス内でエラーが発生したことを意味します。mysqlclient パッケージのインストール中にエラーが発生した模様。そこで、必要なモジュールをインストールします。

  1. 解決策
sudo apt update
sudo apt upgrade
sudo apt install libmysqlclient-dev    # ⬅ インストールされているDBがMySQLの場合
# または
sudo apt install libmariadb-dev    # ⬅ インストールされているDBがMariaDBの場合

その後、pip install mysqlclient を実行すると、mysqlclientのインストールに成功!!
その後、python manage.py runserverで正常にサーバーが起動しました。

結論

  • django(v5.16)にmysqlと接続するときはmysqlclientをインストールすること。
  • インストール中に「This error originates from a subprocess」のエラーが出るときは、libmysqlclient-devもしくはlibmariadb-devのどちらかを先にインストールします。

DockerコンテナのMySQLと接続

以下の"dopcker-compose.yml"ファイルから、コンテナを作成します。

# 起動
sudo docker compose up -d

# 停止
sudo docker compose stop

# 再起動
sudo docker compose restart
versionが8.0系のとき

docker-compose.yml

version: "2.18"
services:
  mysql:
    image: mysql:latest  # 8.0.31
    ports:
      - '3326:3306'  # ← ローカルポート3326 とdockerコンテナ内部のポート3306とを接続
    volumes:
      - './mysql_data:/var/lib/mysql'  
    environment:
      MYSQL_ROOT_PASSWORD: root_pass
      MYSQL_DATABASE: django_db 
      MYSQL_USER: dbuser
      MYSQL_PASSWORD: dbuser_pass
  # -- phpmyadminで確認できるようにしています...
  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    depends_on:
      - mysql
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOSTS=mysql
      - PMA_USER=root
      - PMA_PASSWORD=root_pass
    ports:
      - "8098:80"
volumes:
  mysql_data:
    driver: local

このときの"settings.py"のデータベースに関する設定は以下の通りです。

settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_db', 
        #  -- ここを修正する! 
        'USER': 'root',  
        'PASSWORD': 'root_pass',  # ← rootユーザーのパスワード
        'HOST': '127.0.0.1',     #  ← IPアドレスを入れる (※普通は127.0.0.1に設定されているはず)
        'PORT': '3326',              #  ← local port を入れる
    }
}

これで"python manage.py runserver"で起動すると正常に起動しました。動的に切り替えたいので、この間でもローカルホストではmysqlサーバーが起動しているものとします。

設定におけるポイント

  • HOST名にはドメイン名(localhost)を使わずIPアドレス(127.0.0.1)で記述する。
  • PORT番号にはローカル側のポート番号を記入する。
  • USERは必ずrootユーザーで入る
versionが5.7系のとき

docker-compose.yml

version: "2.18"
services:
  mysql:
    image: mysql:5.7  
    ports:
      - '3328:3306'
    volumes:
      - './mysql_data:/var/lib/mysql'  
    environment:
      MYSQL_ROOT_PASSWORD: root_pass
      MYSQL_DATABASE: django_db 
      MYSQL_USER: dbuser
      MYSQL_PASSWORD: dbuser_pass
  # -- phpmyadminで確認できるようにしています...
  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    depends_on:
      - mysql
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOSTS=mysql
      - PMA_USER=root
      - PMA_PASSWORD=root_pass
    ports:
      - "8099:80"
volumes:
  mysql_data:
    driver: local

このときの"settings.py"のデータベースに関する設定は以下の通りです。

settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_db', 
        #  -- ここを修正する! 
        'USER': 'root',  
        'PASSWORD': 'root_pass',  # ← rootユーザーのパスワード
        'HOST': '127.0.0.1',     #  ← IPアドレスを入れる
        'PORT': '3328',              #  ← local port を入れる
    }
}

mysqlのversionのみをv8.0.31➡v5.7.42に変更した場合、先程と同様に"python manage.py runserver"で起動しても起動できません。
django.db.utils.NotSupportedError: MySQL 8.0.11 or later is required (found 5.7.42).」のエラーが出ます。

これは、使用中のDjangoがv5.1.6と最新のVersionを使っているにも関わらず、MySQLコンテナのバージョンが5.7.42と古いことが原因です。MySQLのバージョンは8.0.11以降でないといけないと注意されています。

対策

  • Djangoのversionを下げてプロジェクトを作る。
  • Django 4.1はMySQL 5.7をサポートしています。

省略しますが、実際にDjango 4.1に下げて検証したところ上手く起動できました😀
よって、Django v5.1.6でプロジェクトを組む場合はMySQLはv8.0.11以降にしてください。

以上になります。😀

Follow me!