PythonのフルスタックWebフレームワークと言えば、Djangoというくらいに有名です。当然Docker Hubに公式イメージがあるんだと思っていましたが、この通り現在は(実際は2016年からなので随分前から)非推奨(DEPRECATED)となっていました。
非推奨なのであれば自分で作るしかないと思いこの記事を書きました。開発者の皆さんの助けになればいいなと思います。
またDjango REST frameworkも同様に公式イメージがないので手作りする方が安心かなと思いました。
- この記事を読んでできるようになること
- Docker Desktopの使い方
- Pipenvの使い方
- DjangoとDjango REST frameworkの違い
- Djangoのインストール
- Django REST frameworkのプロジェクト作成
- 付録
- まとめ
この記事を読んでできるようになること
- お手元のPCでDjangoを使ったWebアプリ開発ができるようになります。
- PythonのDocker公式イメージを使ってDjango開発環境を構築する方法を学習できます。
- DjangoとDjango REST frameworkを組み合わせたバックエンド開発ができるようになります。
Docker Desktopの使い方
Docker Desktopのインストール方法に関しては以下記事をご参考ください。
Pipenvの使い方
Pipenvの使い方に関しては以下記事をご参考ください。
DjangoとDjango REST frameworkの違い
DjangoはWebアプリケーションフレームワークです。Ruby on Railsなどと同じ位置付けです。
対してDjango REST frameworkは、DjangoにREST APIを組み込むためのライブラリです。
Djangoのインストール
本記事ではターミナルを複数使うので、ターミナル1とターミナル2という形で分けて書いております。
リポジトリ用ディレクトリの作成
コマンド(ターミナル1)
私の場合、リポジトリ関係はホームディレクトリ内のreposというディレクトリ内に保存しています。そこにdjangoというgitプロジェクトを作成しています。ちなみに「~」はチルダといい、ホームディレクトリを意味します。ディレクトリの作成は皆さんのお好きなようにやってください。
mkdir -p ~/repos/drf-on-docker
リポジトリディレクトリの移動
コマンド(ターミナル1)
先ほど作成したディレクトリに移動します。
cd ~/repos/drf-on-docker
PythonのDocker公式イメージへの起動とログイン
コマンド(ターミナル1)
先ほど作成した~/repos/djangoディレクトリをPythonコンテナ内の/appディレクトリにマウントし、コンテナ名をdjangoと名付け、bashでログインします。
docker run -it --rm -v $(pwd):/app -w /app --name django python:latest /bin/bash
pipコマンドのアップグレード
コマンド(ターミナル1)
Pythonイメージは、最初からpipコマンドがインストールされていますが、そのバージョンが古いので予めアップデートしておきます。ここはそんなに重要ではないです。無視しても警告が出るくらいです。
pip install --upgrade pip
出力結果(ターミナル1)
WARNING: Running pip as the ‘root’ user can result in.. という警告が出ていますが、Dockerコンテナ内で作業する以上はrootユーザーになってしまうので無視して大丈夫です。
Requirement already satisfied: pip in /usr/local/lib/python3.12/site-packages (23.2.1)
Collecting pip
Obtaining dependency information for pip from https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl.metadata
Downloading pip-24.0-py3-none-any.whl.metadata (3.6 kB)
Downloading pip-24.0-py3-none-any.whl (2.1 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 3.7 MB/s eta 0:00:00
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 23.2.1
Uninstalling pip-23.2.1:
Successfully uninstalled pip-23.2.1
Successfully installed pip-24.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
pipenvのインストール
コマンド(ターミナル1)
パッケージ管理コマンドのpipenvをインストールします。
pip install pipenv
出力結果(ターミナル1)
Successfully installedから始まるメッセージにpipenvが含まれていればインストールが正常に終了したと判断していいでしょう。同様の警告メッセージが出ますが無視してください。
Collecting pipenv
Downloading pipenv-2023.12.1-py3-none-any.whl.metadata (19 kB)
Collecting certifi (from pipenv)
Downloading certifi-2024.2.2-py3-none-any.whl.metadata (2.2 kB)
Requirement already satisfied: setuptools>=67 in /usr/local/lib/python3.12/site-packages (from pipenv) (69.0.3)
Collecting virtualenv>=20.24.2 (from pipenv)
Downloading virtualenv-20.25.0-py3-none-any.whl.metadata (4.5 kB)
Collecting distlib<1,>=0.3.7 (from virtualenv>=20.24.2->pipenv)
Downloading distlib-0.3.8-py2.py3-none-any.whl.metadata (5.1 kB)
Collecting filelock<4,>=3.12.2 (from virtualenv>=20.24.2->pipenv)
Downloading filelock-3.13.1-py3-none-any.whl.metadata (2.8 kB)
Collecting platformdirs<5,>=3.9.1 (from virtualenv>=20.24.2->pipenv)
Downloading platformdirs-4.2.0-py3-none-any.whl.metadata (11 kB)
Downloading pipenv-2023.12.1-py3-none-any.whl (3.1 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.1/3.1 MB 471.0 kB/s eta 0:00:00
Downloading virtualenv-20.25.0-py3-none-any.whl (3.8 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.8/3.8 MB 1.3 MB/s eta 0:00:00
Downloading certifi-2024.2.2-py3-none-any.whl (163 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 163.8/163.8 kB 1.2 MB/s eta 0:00:00
Downloading distlib-0.3.8-py2.py3-none-any.whl (468 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 468.9/468.9 kB 2.4 MB/s eta 0:00:00
Downloading filelock-3.13.1-py3-none-any.whl (11 kB)
Downloading platformdirs-4.2.0-py3-none-any.whl (17 kB)
Installing collected packages: distlib, platformdirs, filelock, certifi, virtualenv, pipenv
Successfully installed certifi-2024.2.2 distlib-0.3.8 filelock-3.13.1 pipenv-2023.12.1 platformdirs-4.2.0 virtualenv-20.25.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
DjangoおよびDjango REST frameworkのインストール
コマンド(ターミナル1)
djangoおよびdjangorestframeworkをインストールします。
pipenv install django djangorestframework
出力結果
Creating a virtualenv for this project...
Pipfile: /app/Pipfile
Using default python from /usr/local/bin/python (3.12.1) to create virtualenv...
⠋ Creating virtual environment...created virtual environment CPython3.12.1.final.0-64 in 89ms
creator CPython3Posix(dest=/root/.local/share/virtualenvs/app-4PlAip0Q, clear=False, no_vcs_ignore=False, global=False)
seeder FromAppData(download=False, pip=bundle, via=copy, app_data_dir=/root/.local/share/virtualenv)
added seed packages: pip==24.0
activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
✔ Successfully created virtual environment!
Virtualenv location: /root/.local/share/virtualenvs/app-4PlAip0Q
Creating a Pipfile for this project...
Installing django...
Resolving django...
Added django to Pipfile's [packages] ...
✔ Installation Succeeded
Installing djangorestframework...
Resolving djangorestframework...
Added djangorestframework to Pipfile's [packages] ...
✔ Installation Succeeded
Pipfile.lock not found, creating...
Locking [packages] dependencies...
Building requirements...
Resolving dependencies...
✔ Success!
Locking [dev-packages] dependencies...
Updated Pipfile.lock (709498677962b597deb7755151c892205b5602857f054bab7de772221152085a)!
Installing dependencies from Pipfile.lock (52085a)...
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Django REST frameworkのプロジェクト作成
ここからDjango REST frameworkのプロジェクト作成に入ります。
Django REST framework用プロジェクトのディレクトリ作成
コマンド(ターミナル1)
Django REST framework用のプロジェクトディレクトリを作成します。ここではわかりやすくprojectとします。
mkdir project
Django REST framework用プロジェクトのディレクトリへの移動
コマンド(ターミナル1)
先ほど作成したprojectディレクトリに移動します。
cd project
Pipenvシェルの起動
コマンド(ターミナル1)
pipenvの仮想環境にログインします。
pipenv shell
Djangoプロジェクトの作成
Djangoプロジェクトを作成します。最後のドット(.)必要なので注意してください。
コマンド(ターミナル1)
django-admin startproject project .
Djangoプロジェクトディレクトリへの移動
projectディレクトリに移動します。
コマンド(ターミナル1)
cd project/
Djangoアプリケーションの作成
Djangoアプリケーションを作成します。ここではわかりやすくappとします。
コマンド(ターミナル1)
django-admin startapp app
ディレクトリ階層
.
├── Pipfile
├── Pipfile.lock
├── manage.py
└── project
├── __init__.py
├── app
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
データベースマイグレーション
初回のデータベースマイグレーションを行います。
コマンド(ターミナル1)
ディレクトリを移動します。
cd /app
コマンド(ターミナル1)
python manage.py migrate
出力結果
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
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
管理ユーザーの作成
コマンド(ターミナル1)
python manage.py createsuperuser --username admin --email [email protected]
入力&出力結果
パスワードを2回入力してください。
Password:
Password (again):
Superuser created successfully.
Serializersの作成
Serializersとはデータ表現のためのクラスです。今回は project/app/serializers.py を作成します。お好みのIDEかエディタで作成し保存してください。
from django.contrib.auth.models import Group, User
from rest_framework import serializers
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['url', 'username', 'email', 'groups']
class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
fields = ['url', 'name']
Viewsの作成
Viewsは他のWebフレームワークでいうところのビジネスロジックにあたるところです。今回はproject/app/views.py を作成します。
from django.contrib.auth.models import Group, User
from rest_framework import permissions, viewsets
from project.app.serializers import GroupSerializer, UserSerializer
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated]
class GroupViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = Group.objects.all()
serializer_class = GroupSerializer
permission_classes = [permissions.IsAuthenticated]
URLsの作成
URLsは他のWebフレームワークでいうところのディスパッチャです。どのパスにアクセスしてきた時にどのメソッドを呼び出すかなどを定義します。今回はproject/urls.py を作成します。
from django.contrib import admin
from django.urls import path
from django.urls import include, path
from rest_framework import routers
from project.app import views
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]
urlpatterns += router.urls
Settings
SettingsはDjangoの設定ファイルです。今回はproject/settings.pyを作成します。
Pagination
ページネーションとは表示件数が多い時などに一定の件数ずつ表示する機能です。
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}
Django REST frameworkの設定
INSTALLED_APPSに ‘rest_framework’, を追加しください。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
]
Dockerイメージの保存
コマンド(ターミナル2)
ここまでの状態をDockerイメージとして保存したいと思います。そのためには、別ターミナルを開きdjangoコンテナのIDを知る必要があります。別ターミナルから以下コマンドを実行してください。
docker ps -a | grep django
出力結果(ターミナル2)
一番左に出るIDがコンテナIDです。それをコピーしてください。
892f0a022dec python:latest "/bin/bash" 2 minutes ago Up 2 minutes django
ちなみにターミナル1側のプロンプトに表示されているroot@以下のコロンまでの間の値もコンテナIDになりますのでそちらをコピーしても大丈夫です。
root@892f0a022dec:/app#
コマンド(ターミナル2)
先ほど開いた別ターミナルでDockerイメージを保存します。docker commitコマンドを使用し、-aオプションには’作者の名前 <メールアドレス>‘、-mオプションにはコミットメッセージ、先ほどコピーしたコンテナID、コンテナのイメージ名を指定します。
docker commit -a '名前 <メールアドレス>' -m 'Install django' 892f0a022dec django:latest
コマンド(ターミナル1)
/bin/bashでログインしているターミナルは不要になったのでDockerコンテナからログアウトします。
exit
Django開発サーバの起動
コマンド
Djangoの開発用サーバを起動します。注意点としてはDockerコンテナとして起動するので、0.0.0.0:8000が重要になってきます。これがないとデフォルトで127.0.0.0:8000で起動することになり、あくまでコンテナ内部でしかアクセスできない形になってしまいます。また-pオプションで8000:8000を指定していますがこちらも重要です。これはコンテナで待ち受けている8000番ポートを自身のPCの8000番ポートに転送する設定になります。
docker run -it --rm -v $(pwd):/app -p 8000:8000 --name django django:latest pipenv run python manage.py runserver 0.0.0.0:8000
動作確認
トップ画面(ログイン前)
このURL http://localhost:8000 にアクセスしてみましょう。 以下のようなページが表示されるはずです。またアクセスするたびにターミナルにアクセスログが記録されることが確認できると思います。右上にあるログインボタンでログインすることができます。
ログイン画面
トップ画面(ログイン後)
ログイン後の画面です。右上がadminになっています。Django REST frameworkだとログアウトできないので、Django Adminからログアウトすれば、Djang REST frameworkからもログアウトされます。
User List
User Listへのアクセスした様子。resultsキーが配列で返ってきていることがわかります。
User Instance
User Listへのアクセスした様子。User IDとして指定したデータだけ返ってきています。
付録
ここまでターミナル1で構築し、ターミナル2で docker commit を行うという方法でやってきましたが、毎回こういうことは実施しません。これまでの手順をDockerfileにまとめてすぐ実行できるようにしました。また今後の拡張性を考慮し、docker composeコマンドで起動できるようにしております。やり方はREADME.mdに書かれておりますのでその通りに実行してください。
まとめ
PythonのオフィシャルDockerイメージを使って、一気にDjango Rest frameworkを動かすところまで見てきました。基本的にはコピペで構築できるようになっているはずです。今回は開発環境としての環境構築手順になります。本番環境ではアプリケーションサーバをuWSGIとGunicornなどにする必要がありますし、静的コンテンツなどを抜き出してWebサーバに配置したりなどすること盛りだくさんです。なのでこの手順を本番環境で使うのはやめましょう。
GunicornでDjangoアプリを動かす方法については以下記事を参照ください。
DjangoのデータベースをPostgreSQLに変更する方法は以下記事を参照ください。
コメント