🙄

Django + MySQL を Docker で構築してユーザー登録する手順

に公開

はじめに

本記事では、ユーザー登録機能を持つ仮想Webアプリケーションを作成しました。
環境は Docker Compose 上で Django(Webフレームワーク)と MySQL(データベース)を連携させて構築しています

この構成により、アプリケーションとデータベースを分離し、ローカル環境に依存しない開発環境を再現できます。
ユーザー登録フォームを作成し、入力したデータが MySQL に保存されることを確認するところまでをまとめています

環境

  • Docker / Docker Compose
  • Python 3.12
  • Django 5.0
  • MySQL 8.3

エディタはVSCodeで、Docker拡張機能を使用しています

作業手順

1. Django 環境の構築

  • Dockerfile と docker-compose.yml を用意して、Django コンテナ(web)を作成
  • Python と必要なパッケージ(Django など)をインストール
  • Django プロジェクトを新規作成(例:myproject)

2. MySQL データベースの構築

  • docker-compose.yml 内で MySQL コンテナ(db)を設定
  • 永続化用のボリュームを作成
  • settings.py で Django と MySQL を接続
  • migrate コマンドで初期テーブルを作成

3. アプリの作成とユーザー登録機能の実装

  • Django アプリ(例:accounts)を作成
  • models.py にユーザーモデルを定義
  • forms.py にユーザー登録フォームを作成
  • views.py と urls.py を設定してフォーム画面を表示
  • 登録フォームから入力したデータが MySQL に保存されることを確認

4. 動作確認

  • コンテナを起動 (docker compose up)
  • ブラウザで http://localhost:8000 にアクセス
  • ユーザー登録画面からフォーム送信
  • MySQL コンテナ内で登録データを確認 (SELECT * FROM users;)

プロジェクト構成

アプリ作成後のディレクトリ構造は以下のようになります

app/
├─ docker-compose.yml
├─ Dockerfile
├─ requirements.txt
├─ djangopj/
│  ├─ __init__.py
│  ├─ asgi.py
│  ├─ settings.py      ← Django全体の設定(DB接続など)
│  ├─ urls.py          ← ルーティング設定
│  ├─ wsgi.py
├─ core/
│  ├─ __init__.py
│  ├─ admin.py
│  ├─ apps.py
│  ├─ models.py        ← 今回は空でもOK
│  ├─ views.py         ← signup・dashboardを記述
│  ├─ tests.py
│  ├─ migrations/
│      └─ __init__.py
├─ templates/
│  ├─ signup.html
│  ├─ login.html
│  └─ dashboard.html
└─ static/
   └─ images/
      ├─ img1.jpg
      ├─ img2.jpg
      ├─ img3.jpg
      ├─ img4.jpg
      └─ img5.jpg
  • djangopj/:プロジェクト全体の設定をまとめる場所
  • core/:実際のアプリロジックを記述(views.pyなど)
  • templates/:HTMLテンプレート置き場
  • static/:CSS・画像などの静的ファイル置き場

Django環境作成手順

webコンテナ(Django)とdbコンテナ(MySQL)のコンテナを立てます

1. 作業ディレクトリを作成

まずは開発用のディレクトリを作成します

mkdir app
cd app

2.必要ファイルを準備

以下の3つを用意します。

  • docker-compose.yml
  • Dockerfile(web用)
  • requirements.txt

docker-compose.yml

services:          
  db:
    image: mysql:8.3   
    environment:             
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: django-db
      MYSQL_USER: django
      MYSQL_PASSWORD: django
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
  web:
    build: .       
    command: python3 manage.py runserver 0.0.0.0:8000 
    volumes:               
      - .:/code
    ports:                  
      - "8000:8000"
    depends_on:             
      - db

Dockerfile

FROM python:3.12.4     
ENV PYTHONUNBUFFERED=1  
RUN mkdir /code        
WORKDIR /code        
COPY requirements.txt /code/   
RUN pip install --upgrade pip && pip install -r requirements.txt
COPY . /code/

requirements.txt

Django==5.0 
mysqlclient

3. Djangoプロジェクト作成

docker compose run web django-admin startproject djangopj .

djangopj/settings.pyを編集してMySQLに接続できるようにします

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django-db',
        'USER': 'django',
        'PASSWORD': 'django',
        'HOST': 'db',
        'PORT': '3306'
    }
}

4. マイグレーション

マイグレーションを行いMySQLとの接続を行います

docker compose run web python manage.py migrate

5. コンテナ起動

コンテナを立ち上げサイトにアクセスできるか確認します

docker compose up -d

コンテナが立ち上がったら
http://localhost:8000 にアクセスし、以下の画面が表示されるか確認します

6. MySQLにDjango用のDBが作られているかを確認します

6.1. DBコンテナの中に入ります

docker exec -it form-db-1 bash

6.2. MySQLにログインします

mysql -u root -proot

6.3. DBを確認します

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| django-db          |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

django-dbが作成されていることを確認できました

アプリ作成

ここからは、Django プロジェクトにアプリを追加し、ユーザー登録フォームを作成して実際に MySQL に保存されるところまでを確認します

1. アプリ作成

Django プロジェクト直下にcoreという名のアプリを作成します

docker compose exec web python manage.py startapp accounts core

2. djangopj/settings.pyに設定を追加します

2.1. INSTALLED_APPSに追加します

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'core',  # ← 追加
]

2.2. テンプレートの場所を指定します
プロジェクト直下のtemplates/を優先して読むための設定です

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],  # プロジェクト共通テンプレート
        "APP_DIRS": True,                  # 各アプリ内の templates/ も読む
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

2.3. 認証時のリダイレクト先

LOGIN_URL = "login"
LOGIN_REDIRECT_URL = "dashboard"
LOGOUT_REDIRECT_URL = "login"
  • ログインページのURL名
  • ログイン後/ログアウト後に飛ばす先のURL名

2.4. 静的ファイルの配信
BASE_DIR / "static"を追加して静的ファイルの保存先を作成します

STATIC_URL = "static/"
STATICFILES_DIRS = [BASE_DIR / "static"]

2.5. 言語・タイムゾーン

  • 日本語・日本時間で表示
  • USE_TZ=TrueでDBはUTC、表示は Asia/Tokyo に変換
LANGUAGE_CODE = "ja"
TIME_ZONE = "Asia/Tokyo"
USE_I18N = True
USE_TZ = True

3. URLを紐づける

djangopj/urls.pyにアプリをインクルードします
ここではログイン・ログアウト・新規登録・トップページ のURLを設定しています

from django.contrib import admin
from django.urls import path
from django.contrib.auth import views as auth_views
from core import views as core_views

urlpatterns = [
    path("admin/", admin.site.urls),
    path("login/", auth_views.LoginView.as_view(template_name="login.html"), name="login"),
    path("logout/", auth_views.LogoutView.as_view(), name="logout"),
    path("signup/", core_views.signup, name="signup"),
    path("", core_views.dashboard, name="dashboard"),
]

4. ユーザー登録の仕組みcore/views.pyの編集

フォームの送信処理とページ表示を行うビューを追加します

import random
from datetime import timedelta
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm

@login_required
def dashboard(request):
    now = timezone.localtime()

    # static/images 内のファイル名
    images = [
        "images/img1.jpg",
        "images/img2.jpg",
        "images/img3.jpg",
        "images/img4.jpg",
        "images/img5.jpg",
    ]
    random_image = random.choice(images)

    return render(request, "dashboard.html", {
        "now": now,
        "random_image": random_image,
    })

def signup(request):
    if request.method == "POST":
        form = UserCreationForm(request.POST)
        if form.is_valid():
            form.save()  # ユーザー作成
            return redirect("login")  # 登録後はログイン画面へ
    else:
        form = UserCreationForm()
    return render(request, "signup.html", {"form": form})

5. テンプレートを用意する

templates/
 ├─ signup.html
 ├─ login.html
 └─ dashboard.html

各ページにアクセスしたときに表示されるページを作成します

5.1. templates/dashboard.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>ダッシュボード</title>
</head>
<body>
  <h1>ダッシュボード</h1>
  <p>{{ user.username }} さん、ログイン中です。</p>

  <p>現在時刻: {{ now|date:"Y-m-d H:i:s" }}</p>

  <img src="/static/{{ random_image }}" alt="random image" style="max-width:400px;">

  <form method="post" action="{% url 'logout' %}">
    {% csrf_token %}
    <button type="submit">ログアウト</button>
  </form>
</body>
</html>

5.2. templates/login.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ログイン</title>
</head>
<body>
    <h1>ログイン</h1>
    {% if form.errors %}
        <p style="color: red;">ユーザー名またはパスワードが間違っています。</p>
    {% endif %}
    <form method="post">
        {% csrf_token %}
        <p>
            <label for="id_username">ユーザー名:</label>
            {{ form.username }}
        </p>
        <p>
            <label for="id_password">パスワード:</label>
            {{ form.password }}
        </p>
        <button type="submit">ログイン</button>
    </form>

    <p>アカウント未作成ですか?
        <a href="{% url 'signup' %}">新規登録はこちら</a>
    </p>
</body>
</html>


5.3. templates/signup.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>新規登録</title>
</head>
<body>
    <h1>新規登録</h1>
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">登録</button>
    </form>

    <p>すでにアカウントをお持ちですか?
        <a href="{% url 'login' %}">ログインはこちら</a>
    </p>
</body>
</html>

6. static(画像を配置する)

static/
  images/
    img1.jpg
    img2.jpg
    img3.jpg
    img4.jpg
    img5.jpg

画像ファイル名はviews.pyの配列 と一致させること

動作確認

docker compose exec web python manage.py migrate
docker compose up -d

http://localhost:8000/ にアクセス

  • /signup/ → ユーザー登録
  • /login/→ ログイン
  • /→ ダッシュボード(時刻+ランダム画像)
    ブラウザで上記ページが表示されれば成功です

MySQLでユーザー情報を確認

web上で作成したアカウントがMySQLに保存されているかを確認します

docker exec -it form-db-1 bash
mysql -u root -proot
use django-db;
SELECT id, username, date_joined FROM auth_user;

出力例:

+----+----------+---------------------+
| id | username | date_joined         |
+----+----------+---------------------+
|  1 | testuser | 2025-10-09 12:34:56 |
+----+----------+---------------------+

まとめ

本記事では、以下の内容を実装しました:

  • Django + MySQL + Docker 環境構築
  • ユーザー登録/ログイン機能の実装
  • MySQLにユーザーデータが保存されることの確認

Discussion