DockerでDjangoを構築しよう
Dockerは今や効率的な開発や安定する本番環境の構築に欠かせない技術となってきました。
そこで、今回はDockerを使ってアプリ開発をしていきます。
身につければ効率的な環境構築ができるので今のうちに身につけておきましょう!
(本サイトはアフィリエイト広告を利用しています)
Dockerとは?
Dockerはコンテナ型仮想環境用のプラットフォームで、軽量で高速に動作します。
Dockerの概要
DockerではPythonやPostgresqlなどのリソースがまとめられたパッケージをコンテナと呼び、それらを組み合わせることでアプリを構築できます。
DockerはMacやWindowsなどのOSの上に配置され、その上にアプリを構築できます。
アプリ開発者がDockerを知るべき3つの理由
どの環境でも動くアプリが開発できる
アプリはプログラムやデータベース、Webサーバーなどさまざまなリソースが組み合わさって作成されています。これらのリソースにはバージョンや開発しているパソコン・本番用サーバーとの相性で動作しないなどの不具合が起こることがあります。
Dockerを使用すると、それぞれのリソースをコンテナとしてパッケージ化できるのでバージョンやリソース間の依存関係を管理できます。このことで、開発環境から本番環境まで、異なる環境間での一貫性を維持しやすくなります。
効率的な開発とデプロイができる
Dockerは独立した環境を提供するため、アプリのデプロイや拡張が簡単です。これによって全体の開発サイクルを高速で回せて効率的な開発ができます。
リソースを仮想化して最適化できる
Dockerは仮想化技術を使用しているので開発者のOSに関係なくリソースを共有できます。これにより、リソースを効率的に利用できます。
また、コンテナはホストOS上で動くため、OSとセットで動作する仮想マシンよりも軽量で高速に起動します。これによって物理サーバーやクラウド環境内でのリソースを最適化できます。
Docker Desktopをダウンロード
Docker Desktopをダウンロード
Docker DesktopのページににアクセスしてDocker Desktopをダウンロードします。
ダウンロードしてDockerのデスクトップアプリを起動できたら成功です。
DockerでDjangoの環境を構築する
プロジェクトフォルダの作成
「docker-django」フォルダをDesktopに作成し、VSCodeで表示します。
環境構築(準備)
プロジェクトフォルダの中に環境構築に必要なファイルを作成していきます。
プロジェクトファイル直下に「Dockerfile」を作成し、以下のように記載します。
Dockerfile
---------------------------------------------------------------------------
FROM python:3.11
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
プロジェクトファイル直下に「requirements.txt」を作成し、以下のように記載します。
requirements.txt
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
asgiref==3.7.2
Django==4.2.4
sqlparse==0.4.4
typing_extensions==4.7.1
psycopg2
psycopg2-binary
このファイルは 「Dockerfile」 内の 「RUN pip install -r requirements.txt」 というコマンドで内容を読み込んでライブラリをインストールしています。
プロジェクトファイル直下に「docker-compose.yml」を作成し、以下のように記載します。
docker-compose.yml
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
version: "3"
services:
db:
image: postgres
environment:
POSTGRES_PASSWORD: "password123"
web:
build: .
command: python3 todo_project/manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
このファイルではDBであるpostgresqlとwebであるDjangoを分けてコンテナを作成します。
dbではpostgresqlの設定を、webではDjangoの設定をしています。
Djangoプロジェクトの生成
Docker Desktopが起動しているか確認します。
その後、VSCodeのターミナルで以下のコマンドを実行します。
docker-django % docker-compose run web django-admin startproject todo_project
コマンドを実行すると、「todo_project」フォルダが作成されます。
DBへの接続
「todo_project/todo_project/settings.py」を開き、DBを設定している部分を書き換えます。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': 'password123',
'HOST': 'db',
'PORT': 5432,
}
}
DBの設定は「postgres」のDocker イメージが設定している内容です。
ターミナルで以下のコマンドを実行すると
docker-django % docker-compose up
Dockerを確認すると、dbとwebが起動していることが確認できます。
docker-django_wetはDjangoのtodo_projectを作成したときの副産物なので削除します。
チェックボックスにチェックするとDeleteボタンが表示されるのでクリックします。
http://localhost:8000/ にアクセスしてDjangoのページが表示されれば成功です。
Todoアプリの作成
いよいよTodoアプリを作成していきます。
Todoアプリのコードは下の記事には書いてあるのですが、今回はDockerを使っているのでDocker用に書いていきます。
Dockerを使うことでPythonの仮想環境を作らずに開発でき、他の環境でも構築できるようになります。
アプリ(機能)を作成
web-1コンテナの中に入り、todo_projectフォルダ直下まで移動して開発するアプリのフォルダを作成します。
docker-django % docker exec -it docker-django-web-1 bash
root@eb191ba4f99a:/code#
root@1ffe070f2e87:/code# cd todo_project/
root@1ffe070f2e87:/code/todo_project# python manage.py startapp todo
root@1ffe070f2e87:/code/todo_project#
「todo_project/todo_project/settings.py」の「INSTALLED_APPS」に以下のように追加することでプロジェクトとアプリの機能を紐付けます。
todo_project/todo_project/settings.py
---------------------------------------------------------------------------
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'todo' # アプリの機能を追加
]
設定言語を日本語に、タイムゾーンを東京にします。
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
アプリ開発(モデルの作成)
models.pyにデータの定義を書き込む
「todo_project/todo/models.py」に以下のように書き込みます。
todo_project/todo/models.py
---------------------------------------------------------------------------
from django.db import models
# Todoに入れるデータを定義する。
class TodoTask(models.Model):
title = models.CharField(max_length=200)
description = models.TextField(blank=True,null=True)
completed = models.BooleanField(default=False)
def __str__(self) -> str:
return self.title
マイグレーションでアプリとDBに接続する
DBに反映させるためのPythonコードを生成します。
root@1ffe070f2e87:/code/todo_project# python manage.py makemigrations
Migrations for 'todo':
todo/migrations/0001_initial.py
- Create model TodoTask
root@1ffe070f2e87:/code/todo_project#
生成されたPythonコードをDBに反映します。
root@1ffe070f2e87:/code/todo_project# python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, todo
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 todo.0001_initial... OK
root@1ffe070f2e87:/code/todo_project#
アプリ開発(ビューの作成)
「views.py」に機能を追加する
「todo_project/todo/views.py」に以下のように書き込みます。
todo_project/todo/views.py
---------------------------------------------------------------------------
from django.shortcuts import render, redirect, get_object_or_404
from .models import TodoTask
from .forms import TodoTaskForm
# Todoのリストを表示する機能
def todo_list(request):
tasks = TodoTask.objects.all()
return render(request, 'todo/todo_list.html', {'tasks': tasks})
# Todoを作成する機能
def todo_create(request):
if request.method == 'POST':
form = TodoTaskForm(request.POST)
if form.is_valid():
form.save()
return redirect('todo_list')
else:
form = TodoTaskForm()
return render(request, 'todo/todo_form.html', {'form': form})
# Todoを更新する機構
def todo_update(request, pk):
task = get_object_or_404(TodoTask, pk=pk)
if request.method == 'POST':
form = TodoTaskForm(request.POST, instance=task)
if form.is_valid():
form.save()
return redirect('todo_list')
else:
form = TodoTaskForm(instance=task)
return render(request, 'todo/todo_form.html', {'form': form})
# Todoを削除する機能
def todo_delete(request, pk):
task = get_object_or_404(TodoTask, pk=pk)
if request.method == 'POST':
task.delete()
return redirect('todo_list')
return render(request, 'todo/todo_confirm_delete.html', {'task': task})
アプリ開発(フォームの作成)
「forms.py」にフォーム機能を追加する
「todo_project/todo/forms.py」に以下のように書き込みます。
todo_project/todo/forms.py
---------------------------------------------------------------------------
from django import forms
from .models import TodoTask
class TodoTaskForm(forms.ModelForm):
class Meta:
model = TodoTask
fields = ['title','description','completed']
アプリ開発(テンプレートの作成)
次はテンプレートを作成していきます。以下の場所にtemplatesフォルダを作成してHTMLを作成します。
todo_project/todo
「todo_list.html」にTodoリストを表示する
todo_list.htmlを作成して以下のコードを記載します。
todo_project/todo/templates/todo/todo_list.html
---------------------------------------------------------------------------
<!DOCTYPE html>
<html>
<head>
<title>Todoリスト</title>
<!-- Bootstrap CSSリンクを追加 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
/* 取り消し線のスタイルを定義 */
.completed-task {
text-decoration: line-through;
}
</style>
</head>
<body>
<div class="container mt-5">
<h1 class="mb-4">Todoリスト</h1>
<div class="row">
{% for task in tasks %}
<div class="col-md-4 mb-4">
<div class="card">
<div class="card-body">
<h5 class="card-title {% if task.completed %}completed-task{% endif %}">{{ task.title }}</h5>
<p class="card-text {% if task.completed %}completed-task{% endif %}">{{ task.description }}</p>
<div class="d-flex justify-content-between">
<a href="{% url 'todo_update' task.pk %}" class="btn btn-sm btn-primary">更新</a>
<a href="{% url 'todo_delete' task.pk %}" class="btn btn-sm btn-danger">削除</a>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<a href="{% url 'todo_create' %}" class="btn btn-primary mt-3">新しいタスクを作成</a>
</div>
<!-- Bootstrap JSとPopper.jsのリンクを追加 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
「todo_form.html」にTodoを送信するフォームを表示する
todo_form.htmlを作成して以下のコードを記載します。
todo_project/todo/templates/todo/todo_form.html
---------------------------------------------------------------------------
<!DOCTYPE html>
<html>
<head>
<title>{% if form.instance.pk %}Todoを更新{% else %}Todoを作成{% endif %}</title>
<!-- Add Bootstrap CSS link -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<div class="card">
<div class="card-body">
<h1 class="card-title">{% if form.instance.pk %}Todoを更新{% else %}Todoを作成{% endif %}</h1>
<form method="post">
{% csrf_token %}
<div class="mb-3 row">
<label for="{{ form.title.id_for_label }}" class="col-sm-2 col-form-label">タイトル</label>
<div class="col-sm-10">
{{ form.title }}
</div>
</div>
<div class="mb-3 row">
<label for="{{ form.description.id_for_label }}" class="col-sm-2 col-form-label">説明</label>
<div class="col-sm-10">
{{ form.description }}
</div>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="{{ form.completed.name }}"
id="{{ form.completed.id_for_label }}" {% if form.completed.value %}checked{% endif %}>
<label class="form-check-label" for="{{ form.completed.id_for_label }}">完了済み</label>
</div>
<div class="d-grid gap-2">
<input type="submit" value="Save" class="btn btn-primary">
</div>
</form>
</div>
</div>
</div>
<!-- Add Bootstrap JS and Popper.js links -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
「todo_confirm_delete.html」に削除の確認を表示する
todo_confirm_delete.htmlを作成して以下のコードを記載します。
todo_project/todo/templates/todo/todo_confirm_delete.html
---------------------------------------------------------------------------
<!DOCTYPE html>
<html>
<head>
<title>Todoを削除</title>
<!-- Add Bootstrap CSS link -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h1>Todoを削除</h1>
<div class="card">
<div class="card-body">
<p class="card-text">「{{ task.title }}」を削除しますか?</p>
<form method="post">
{% csrf_token %}
<input type="submit" value="削除" class="btn btn-danger">
</form>
</div>
</div>
</div>
<!-- Add Bootstrap JS and Popper.js links -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
アプリ開発(ルートの作成)
アプリ(機能)のルートを設定
todoフォルダ直下にurls.pyを作成して以下のコードを記載します。
todo_project/todo/urls.py
---------------------------------------------------------------------------
from django.urls import path
from . import views
urlpatterns = [
path('', views.todo_list, name='todo_list'),
path('create/', views.todo_create, name='todo_create'),
path('update/<int:pk>/', views.todo_update, name='todo_update'),
path('delete/<int:pk>/', views.todo_delete, name='todo_delete'),
]
プロジェクトのルートを設定
todo_project/todo_projectフォルダ直下にあるurls.pyに
todo_project/todo_project/urls.py
---------------------------------------------------------------------------
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('todo/', include('todo.urls')),
]
アプリを起動
アプリを起動する
Dockerのdocker-djangoコンテナを起動します。
起動したら以下のurlにアクセスするとTodoアプリがブラウザに表示されます。
http://localhost:8000/todo/
さらに学びたい方へ
Dockerはアプリ開発には欠かせない技術になっています。
Dockerをしようすることで開発環境の統一やアプリの影響を排除できます。本書は、プログラミング初学者でもわかるように、Dockerの基礎知識から開発環境の構築まで、かわいいカエル君と一緒に実際に動作を試しながら学べる入門書です。
詳細はこちら
Djangoの認証機能やフォームシステムを学んでもっと充実したアプリを開発したい方はこちら
まとめ
今回はDockerをしようしてDjangoのTodoアプリを作成しました。Dockerはチーム開発する上で必ず使う技術なので勉強しておいて損はないです。
このチュートリアルをやってみて自分のやってみたい言語やデータベースに変えてDockerで環境構築するのも面白いですね。
未経験からのITエンジニア
IT技術の進化速度が速くなっていっている今、IT技術にアンテナを張っておくことはとても重要です。エンジニアになろうとしている方やそうではない方もITスキルを磨くことで問題解決能力や論理的思考を養うことができます。複雑な課題に対処し、効果的な解決策を見つける能力はどの職種でも重宝されます。
そこで、エンジニア未経験の時にあったらよかったなと思っていた講座をマガジンにまとめました!アプリの基礎がわかるTodoアプリの開発からGit&GitHubでのチーム開発までエンジニアに必要な知識が詰まっています!
エンジニアリングの第一歩として使ってみてください!
「売上げアップに効果的」なキャッチコピーやテキストを作成してくれる国内最大級の「AIコピーライティングツール」
【Catchy】
会議・ミーティングの内容をリアルタイムで文字に起こすAI自動文字起こしサービス
【Notta】
ブログの記事制作にかかる時間を1/10で制作できる高品質SEO記事生成AIツール
【Value AI Writer byGMO】