当サイトは、アフィリエイト広告を利用しています

【Docker × Python】Djangoの開発環境をコンテナで作る

作成日:2023月10月25日
更新日:2023年12月21日

PythonのWEBフレームワークであるDjangoの開発環境を
Dockerコンテナを使って構築してみる。

Dockerコンテナを使って開発環境を構築することで
ローカルマシンには基本的にはDocker以外をインストールしないので
ローカルの環境を汚さずできる。

また開発環境は構築はVScodeの拡張機能であるdevcontainerを使って
VScode上で行い、構築後もVScodeから操作できるようにする。

DockerとDjangoに関しては下記の書籍を参考にした
二冊とも初心者でもかなりわかりやすかったのでおススメです。

環境

Dockerを使ってコンテナ内でDjangoの開発環境を作る
下記の環境で行う

  • Windows10
  • Docker version 24.0.2(Docker for Windows)
  • VScode
  • Devcontainer(VScodeの拡張機能)

Docker for Windowsのインストール方法については下記記事で 紹介しています

devcontainerの詳しい使い方については下記記事で
まとめています

構成

プロジェクトは最終的には下記のような構成になる

プロジェクト
.
├── .devcontainer
│ └── devcontainer.json
├── docker
│ ├── Dockerfile
│ ├── docker-compose.yml
│ └── requirements.txt
└── dockerdjango
├── db.sqlite3
├── djangoapp
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ └── __init__.cpython-310.pyc
│ ├── models.py
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── dockerdjango
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py

各ディレクトリについて下記のような役割

.devcontainer

Dockerコンテナ内の開発をVScodeからできる拡張機能
Devcontainerの設定ファイルを格納している

dockerdjango

Djangoを使ってプロジェクトを開始した時に作成される
ディレクトリ。 ここがDjangoのメインとなる。

docker

Djangoの開発環境コンテナを作成するための
dockerfileなど、コンテナ作成に関わるファイルを格納する

構成は最終的には上記のようになるが
作業中に作っていくファイルもあるのでここからは
順に説明していく。

Dockerコンテナを作る

まずはDjangoを使うためにPythonのコンテナを作成する
コンテナ作成に使うファイルはdockerディレクトリにまとめてある

docker-compose.yml

コンテナはdocker-composeを使って作成する
コンテナはDjangoでWEBアプリを動かすための

  • サーバー用コンテナと
  • クライアント用コンテナ

の二つを用意する
クライアント用コンテナはちょっとした検証に使うので
実際、開発するだけの場合はなくてもいい。

docker-compose.yml
version: "3"
services:
# サーバー
django:
container_name: "django"
# Dockerfileをビルド
build:
context: .
dockerfile: Dockerfile
tty: true
# プロジェクトをバインドマウント
volumes:
- ../:/workspace
# ポートマッピングを指定
ports:
- 8000:8000
# クライアント
client:
container_name: "client"
image: python:3.10
tty: true

各項目について少し解説する

build

  • dockerイメージはdockerfileを使って作る
  • contextではdockerfileの位置を相対パスで指定する

tty

trueにするとコンテナ内で対話的なシェルセッションを開始できる
※コンテナ内に入って操作するならつけといたほうが無難。

volumes

「ホスト側の相対Path:コンテナの絶対Path」で設定し
ホストとコンテナのvolumeをバインドさせる

ここではプロジェクトとworkspaceをバインドさせる
ボリュームにバインドさせることデータは永続化され
仮にコンテナを誤って消してもデータは消えない
※逆に言えば、バインドしていないとコンテナを消した時点で
コンテナの中身も飛ぶので注意!

ports

ホストマシンのポートとコンテナ内のポートのマッピングを指定する
この設定をすれば、コンテナ内のポート8000にはホストのポート8000から
アクセスすることができる。
※ポート番号8000にしているのは8000はDjangoサーバーのデフォルトのポート番号のため
特に使われているとかでなければ8000を指定しておく。

Dockerfile

Djangoコンテナのimageを作るためのDockerfileを作成する

dockerfile
# イメージ
FROM python:3.10
# workspaceディレクトリを作成
WORKDIR /workspace
# workspaceにrequirements.txtをコピー
COPY requirements.txt /workspace/
# requirements.txtのパッケージをインストール
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

必要なパッケージのインストールは

「requirements.txt」

を使って行う

requirements.txt

開発に必要なPythonのパッケージを記述する

requirements.txt
Django==4.2.6

今は開発環境を作るだけなので「Django」のみを
書いている。

プロジェクトで他に必要になった場合はここに追加して
コンテナを作り直す、またはコンテナ内でpip installして対応する。

.devcontainer/devcontainer.json

VScodeの拡張機能であるdevcontainerの設定ファイルも
ここで作成しておく

json
{
// コンテナ名
"name": "dockerdjango",
// コンテナ作成に使うdocker-comopseファイルの相対パス
"dockerComposeFile": "../docker/docker-compose.yml",
// サービス名
"service": "django",
// コンテナ内のプロジェクトのルートフォルダを指定
"workspaceFolder": "/workspace",
// コンテナ停止時のアクション
"shutdownAction": "stopCompose",
// コンテナに入れるVScodeの拡張機能
"extensions": [
"ms-python.python",
"ms-toolsai.jupyter",
"mhutchie.git-graph"
]
}

service

service名はdocker-compose.ymlのservicesで設定したものと
一致させておく。

extensions

extensionsではコンテナにインストールするVScodeの拡張機能
をあらかじめ設定できる

VScodeからコンテナを作る

vscodeのdevcontainerを使ってコンテナを作る Docker for Windowsの場合は、Dockerを起動させておく
※させてないとできないので

コンテナを開くを選択する

F1でコマンドパレットを開いて、「コンテナを再度、開く」
を選択する 2023-10-24-23-07-57

コンテナ画面

コンテナの作成の成功すると
下記のような画面になる 2023-10-24-23-10-32 左下にコンテナ名が表示されている

ファイル

ファイルに関してはプロジェクトごとバインドマウントしているので
そのまま表示されている 2023-10-24-23-12-35

Pythonパッケージの確認

Djangoがインストールされてるか確認する
VScodeのターミナルで下記コマンドで確認できる

bash
$ python -m django --version
4.2.6

ターミナルはdockerに入った状態になっている

ここまででPythonのコンテナの作成は完了

Djangoプロジェクトを作る

Djangoが動かすためのPythonコンテナが作成できたので
実際にDjangoのプロジェクトを作成する

Djangoプロジェクトを作成する

Djangoプロジェクトを作成する
作成は下記コマンドで実行する

bash
django-admin startproject < project-name >

< project-name >に任意のプロジェクト名を設定する
今は「dockerdjango」で進める

bash
django-admin startproject dockerdjango

実行すると下記のようなディレクトリとファイルが作成される

tree
.
├── .devcontainer
│ └── devcontainer.json
├── docker
│ ├── Dockerfile
│ ├── docker-compose.yml
│ └── requirements.txt
└── dockerdjango
├── dockerdjango
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py

Djangoサーバーを起動する

まだこの後、プロジェクト配下にアプリを作成して
いくが、一旦、ここでDjangoサーバーを起動してアクセルできるか
確認する

Djangoサーバーの起動はmanage.pyがあるディレクトリに移動し
下記のコマンドで起動できる

bash
python manage.py runserver

Djangoサーバー起動

実際に起動してみる

bash
$ cd dockerdjango/
$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
October 24, 2023 - 14:31:43
Django version 4.2.6, using settings 'dockerdjango.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

起動できたので

http://127.0.0.1:8000/」

アクセスすると
2023-10-24-23-34-36 となり、アクセスできない。

IPとポート番号指定で起動する

次は下記のようにIPとポート番号を指定してDjangoサーバーを起動する

bash
$ python manage.py runserver 0:8000
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
October 24, 2023 - 14:36:23
Django version 4.2.6, using settings 'dockerdjango.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.

そして「http://localhost:8000/」
にアクセスすると
2023-10-24-23-38-11 のようにDjangoの初期画面が表示される

なぜアクセスできないのか?

Dockerのコンテナは、コンテナがそれぞれ独立した環境を持っているため
デフォルトではホストOSからアクセスできない状態になっている

そしてDjangoサーバーがデフォルトで待ち受けるIPアドレスが127.0.0.1(localhost)
のためIP、ポート番号なしで起動してもホストからはアクセスできない。

そのため起動時に

  • IPアドレスを0.0.0.0(すべてのIPアドレス)に設定
  • ポート番号を8000に設定(docker-compose.ymlでポートマッピングした値)

を指定して起動することでホストからアクセス可能になる。

ここまでで一応、Djangoプロジェクトを起動できたが
実際使う時はアプリを作るとおもうので簡単なアプリまで作ってみる

アプリを作る

Djangoにおける「アプリ(App)」は
Django Webフレームワーク内の機能的なコンポーネントのことで
アプリケーション内の特定の機能セットを実装し、管理するための独立したモジュールになる。

イメージとしては下記のような感じ
2023-10-24-23-51-50 プロジェクトに機能ごとのコンポーネント(アプリ)
がぶら下がっているイメージ

アプリを作る

実際にアプリを作ってみる
アプリはmanage.pyがあるフォルダで下記コマンドを実行する

bash
python manage.py startapp < app-name >

今は「djangoapp」で作る

bash
python manage.py startapp djangoapp

作成後は下記のような構成になる

bash
.
├── .devcontainer
│ └── devcontainer.json
├── docker
│ ├── Dockerfile
│ ├── docker-compose.yml
│ └── requirements.txt
└── dockerdjango
├── db.sqlite3
├── djangoapp
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── dockerdjango
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-310.pyc
│ │ ├── settings.cpython-310.pyc
│ │ ├── urls.cpython-310.pyc
│ │ └── wsgi.cpython-310.pyc
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py

アプリができたので簡単に実装して
動かしてみる

Djangoの実装

プロジェクト(dockerdjango)とそれにぶら下がっているアプリ(djangoapp)
を作ったので実際に実装して動かしてみる。

アプリをプロジェクトに追加する

まずは作成したアプリをプロジェクトにする

dockerdjango/dockerdjango/settings.py
~
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'djangoapp.apps.DjangoappConfig'
]
~

「DjangoappConfig」は下記のクラス名と合わせる

dockerdjango/djangoapp/apps.py
from django.apps import AppConfig
class DjangoappConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'djangoapp'

urls.pyの編集

DjangoウェブアプリケーションのURLパターンとビューを定義するためのファイル
URLのパスとそれに関連するビュー関数をマッピングする

プロジェクトとアプリにそれぞれurls.pyあるので編集する
※ない場合は作る

アプリのurls.py

アプリのurls.pyから作る
アプリのurls.pyは自動で作成されないので自分で作る。

dockerdjango/djangoapp/urls.py
from django.urls import path
from .views import djangoappfunc
urlpatterns = [
path('djangoapp/', djangoappfunc),
]

「djangoapp/」のpathでdjangoappfunc関数(あとで作る)を
呼び出すように設定しておく。

プロジェクトのurls.py

次はプロジェクトのurls.pyを編集する
※こちらは自動で作成されてている

dockerdjango/dockerdjango/urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('app/', include('djangoapp.urls')),
]

includeでdjangoappのurls.pyを読み込むように設定する
これで'app'でアクセスが来た場合、アプリのurls.pyのパターンを
探しにいくようになる

これで

「http://localhost:8000/app/djangoapp/」

にアクセスするとdjangoappfunc関数の戻り値が画面に表示される

views.pyの編集

urlのマッピング設定はできたので、次はviews.pyで
djangoappfunc関数を定義する

dockerdjango/djangoapp/views.py
from django.http import HttpResponse
def djangoappfunc(request):
return HttpResponse("hello world")

文字列を返すだけの関数を実装しておく。

Djangoプロジェクトの起動確認

実装は終わったので実際に動かして動作を確認してみる

Djangoサーバー起動

Djangoサーバーの起動はmanage.pyがあるディレクトリで
下記コマンドを実行する

bash
$ python manage.py runserver 0:8000

繰り返しになるが、Dockerコンテナの中でDjangoサーバーを
起動しているのでホストのブラウザからアクセスするために

  • IPは0.0.0.0
  • ポート番号は8000(docker-compose.ymlで指定したポート)

で起動する。

起動後、「http://localhost:8000/app/djangoapp/」に
アクセスすると下記のようになる
2023-10-25-21-45-10

ALLOWED_HOSTSのエラーが出る場合

bash
~
HTTP request sent, awaiting response... 400 Bad Request
2023-11-02 16:53:49 ERROR 400: Bad Request.
~

上記のような通信エラーがでる場合は
setting.pyのALLOWED_HOSTSを設定することで解決できる

settings.pyのALLOWED_HOSTSに全てを許可するようにしておく

settings.py
ALLOWED_HOSTS = ['*']

DjangoのALLOWED_HOSTS設定は
ウェブアプリケーションが受け入れることが許可されている
ホスト(ドメインまたはIPアドレス)のリストを指定するための重要なセキュリティ設定

開発時は「*」でいいが、本番にあげる時は厳密に設定する必要がある。

クライアントコンテナからDjangoサーバーにアクセスする

ホストからではなく別のコンテナ(クライアントコンテナ)
からアクセスしてみる。

同様に下記コマンドでDjangoサーバーを起動する

bash
$ python manage.py runserver 0:8000

そしてクライアントコンテナから「http://localhost:8000/app/djangoapp/」
に対してアクセスをwgetで行うと下記のようなエラーとなる

クライアントコンテナ
$ wget http://localhost:8000/app/djangoapp/
--2023-10-25 13:03:25-- http://localhost:8000/app/djangoapp/
Resolving localhost (localhost)... 127.0.0.1, ::1
Connecting to localhost (localhost)|127.0.0.1|:8000... failed: Connection refused.
Connecting to localhost (localhost)|::1|:8000... failed: Cannot assign requested address.
Retrying.
~

localhostはホストから見たときの話なので別のコンテナからは
アクセスできない。

別のコンテナからアクセスできるようにする

アクセスするためには
settings.pyのALLOWED_HOSTSにコンテナのサービス名を加える

settings.py
ALLOWED_HOSTS = ['django']

そして
「http://django:8000/app/djangoapp/」

でアクセスしてやれば通信できる

クライアントコンテナ
$ wget http://django:8000/app/djangoapp/
--2023-10-25 13:09:16-- http://django:8000/app/djangoapp/
Resolving django (django)... 172.31.0.2
Connecting to django (django)|172.31.0.2|:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 11 [text/html]
Saving to: ‘index.html.1’
index.html.1 100%[==================================================================================================================>] 11 --.-KB/s in 0s
2023-10-25 13:09:16 (1.48 MB/s) - ‘index.html.1’ saved [11/11]

取得したhtmlを確認すると

index.html
hello world

となっており通信できることがわかる

コンテナ起動と同時にDjangoサーバーを立ち上げる

最初はプロジェクトがないので、Djangoサーバーを起動させることは
できないが、プロジェクト作成後はdocker-composeで実行時に一緒に
Djangoサーバーを起動させるようにできる

docker-compose.yml
version: "3"
services:
# サーバー
django:
container_name: "django"
# Dockerfileをビルド
build:
context: .
dockerfile: Dockerfile
tty: true
# プロジェクトをバインドマウント
volumes:
- ../:/workspace
# ポートマッピングを指定
ports:
- 8000:8000
# Djangoサーバーを起動するコマンドを追加
# command: ["python", "/workspace/djangoPararel/dockerdjango/manage.py", "runserver", "0:8000"]
command: >-
python /workspace/dockerdjango/manage.py runserver 0:8000
# クライアント
client:
container_name: "client"
image: python:3.10
tty: true

docker-compose.ymlにサーバーを起動するコマンドを追記する

まとめ

Dockerを使ってPythonのDjangoフレームワークを使って開発環境を
構築してみた。
Djangoサーバーと通信するあたりで少しつまづいたが
Dockerの仕様を考えることで解決できた。
まだ使い出したところだがWEBフレームワークとしては
割と使いやすそうと感じた。

構築したコンテナ上のDjangoをVScodeでのデバッグ方法については下記でまとめています

新着記事

top