【面向Django初学者】使用Docker Compose快速搭建Django开发环境(本地环境篇)

这篇帖子是2021年Django Advent Calendar的第24天的文章。

首先

因为在Django的圣诞节日历上感觉到缺少针对初学者的文章,所以我决定为那些打算在年末年初的假期尝试学习Django的人们写一篇文章。

作者

该人在IT行业拥有10年以上的经验,但一直在遗留环境中开发COBOL,如主机等,最近甚至不再编写COBOL,而是完全使用Excel制作文件。对于Django和Python的使用经验也没有,是初学者。

我想写这篇文章的原因

公開起已经两年,我以前用Django制作过第一个网页应用程序。时间过去了,我已经忘记了很多内容,所以在回顾Django开发的同时,我想写一篇文章。以下是我以前创建的应用程序的链接。

网站
星图

Github (hayatek/star-chart)
Github(hayatek/star-chart)

这是一个从Github获取存储库的收藏数量并将其制成图表进行比较的应用程序。
我清楚地知道,仅通过Github的收藏数量无法衡量框架或语言的受欢迎程度,但我认为它可能成为一个指标。
例如,在上述应用程序中,我们可以查看Django、Flask和Rails收藏数量的变化趋势。

グラフ.png

从仅仅看星标数增长来看,我们可以发现Django比Flask或Rails增长得更快。

在第一次创建Web应用程序时,使用Docker和GraphQL的API,进行定期批处理等各种细节实现非常困难,但令人惊喜的是,它在没有太多维护的情况下奇迹般地运行了2年。通过这次使用Django的经验,我认为即使是初学者也能够轻松理解,所以我推荐它。

阻碍初次开发Django应用的因素。

虽然我自己也有过这样的经历,即使想要用Django创建应用程序,但在此之前要安装Python实际上有很多种方法(比如venv、pyenv、anaconda…),容易被其中某一点所困扰。
使用Docker可以解决这些问题,并且使用Docker本身并不是什么很高的门槛。

由於這次時間有限,我想專注於使用Docker運行Django,重新嘗試一次。
正如開頭所說,我自己也是Django的初學者,如果有任何錯誤或不足之處,請給予指正和補充。那麼,我們就開始吧!

这次要制作的东西。

我们将使用Docker和Docker Compose,在本地环境中运行Django。

    • Django

 

    • Docker

 

    Docker-compose

参考视频

因为之前做应用程序的时候也参考了这位的Udemy视频,非常易懂,所以我会一直按照这个视频做下去。关于使用Docker Compose部署Django的方法,请参考上述的博客文章(英文)。

前提(Qian2 ti2)

我使用的是Mac环境,所以将以Mac为基础进行解释。(尽管很可能在Windows上也能实现相同的操作,但我没有确认的方法,因此无法确定。。)
操作系统版本为MacOS Catalina(10.15.7)
Docker桌面版版本为Docker Desktop(4.1.1)

安装Docker桌面版

需要事先安装Docker Desktop。
这里提供了关于如何安装Docker Desktop Mac版的详细解释。

在本教程中,我们将会学习如何在 Mac 上安装 Docker Desktop,并设置 CentOS 的虚拟环境。

首先快速建立开发环境。

那么,让我们立即开始吧。

为了快速地建立环境,事先准备好的模板将被克隆并将相应的 DockerFile、docker-compose 和 requirements.txt 文件复制到本地。

模板文件(Github)
hayatek/docker-django-app

我将克隆上述的存储库。

git clone git@github.com:hayatek/docker-django-app.git

这样一来,docker-django-app文件夹(项目的根文件夹)将具有以下结构。

project root.png

在同一层级下创建.dockerignore文件。

使用以下内容创建.dockerignore文件。此文件用于在构建Docker镜像时不将不必要的文件添加到Docker镜像中。即使没有此文件,Docker也可以运行。

# Git
.git
.gitignore

# Docker
.docker

# Python
app/__pycache__/
app/*/__pycache__/
app/*/*/__pycache__/
app/*/*/*/__pycache__/
.env/
.venv/
venv/

# Local PostgreSQL data
data/

项目的构建

当您在终端中导航至项目的根文件夹后,请执行以下操作:构建Docker镜像。

cd docker-django-app #プロジェクトのルートフォルダに移動
docker-compose build

如果没有错误,Docker环境的构建就完成了。

接下来,我们将创建一个Django项目。

docker-compose run --rm app sh -c "django-admin startproject app ."

创建Django项目后,项目的结构如下所示。

Tree.png

设定SECRET_KEY

在app文件夹中编辑创建的settings.py文件。
1. 添加import os语句。
2. 将SECRET_KEY设置为通过os.environ.get()函数访问。

import os #追加
from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get('SECRET_KEY') #変更

本次是因为本地环境的原因,所以将SECRET_KEY设置如下,放在docker-compose.yml中。

environment:
      - SECRET_KEY=devsecretkey

创建应用程序

我們在Django上創建一個名為core的應用程式(應用程式名稱可以是任意的)。
在終端上執行以下命令。

docker-compose run --rm app sh -c "python manage.py startapp core"

在settings.py的INSTALLED_APPS中添加一个名为core的应用程序。

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

将数据库的描述更改为使用postgre。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'HOST': os.environ.get('DB_HOST'),
        'NAME': os.environ.get('DB_NAME'),
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASS'),
    }
}

设定模型

接下来打开app/core/models.py文件。
删除”# Create your models here.”,然后添加以下内容。

from django.db import models


class Sample(models.Model):              #追加
    attachment = models.FileField()    #追加

请打开app/core/admin.py文件,并添加以下内容。

from django.contrib import admin
from core.models import Sample #追加

admin.site.register(Sample) #追加

完成上述设置之后,请在终端中执行以下命令。

docker-compose run --rm app sh -c "python manage.py makemigrations"

等待数据库

使用Docker来运行Django和PostgreSQL似乎存在以下问题。

尽管将depends_on块添加到应用程序服务中可以确保在应用程序之前启动数据库服务,但无法确保数据库已初始化。
这可能导致Django在完全启动之前尝试连接到数据库而导致崩溃的问题。

我们将进行以下设置以避免这个问题。
首先,在下面的路径上创建一个空的init.py文件。

应用程序核心管理的初始化文件 app/core/management/init.py 和 app/core/management/commands/init.py。

在`app/core/management/commands/`下创建一个名为`wait_for_db.py`的文件,并写入以下内容。

"""
Django command to wait for the database to be available.
"""
import time

from psycopg2 import OperationalError as Psycopg2OpError

from django.db.utils import OperationalError
from django.core.management.base import BaseCommand


class Command(BaseCommand):
    """Django command to wait for database."""

    def handle(self, *args, **options):
        """Entrypoint for command."""
        self.stdout.write('Waiting for database...')
        db_up = False
        while db_up is False:
            try:
                self.check(databases=['default'])
                db_up = True
            except (Psycopg2OpError, OperationalError):
                self.stdout.write('Database unavailable, waiting 1 second...')
                time.sleep(1)

        self.stdout.write(self.style.SUCCESS('Database available!'))

等待DB的设置已经完成。

执行Docker Compose

在终端上使用以下命令执行Docker Compose。

docker-compose up

在浏览器中输入http://127.0.0.1:8000/。

Djnago.png

Django在4.0版本开始运行了!

说明

Tree.png
Django==4.0

下面是Dockerfile。
我们将使用Docker Hub上的Python alpine镜像,其中包含了Python的安装程序。
我们将在Run语句中追加以下内容。

FROM python:3.10.1-alpine3.15

ENV PYTHONUNBUFFERED 1

COPY ./requirements.txt /requirements.txt
COPY ./app /app

WORKDIR /app
EXPOSE 8000

RUN python -m venv /py && \
    /py/bin/pip install --upgrade pip && \
    apk add --update --no-cache postgresql-client && \
    apk add --update --no-cache --virtual .tmp-deps \
        build-base postgresql-dev musl-dev && \
    /py/bin/pip install -r /requirements.txt && \
    apk del .tmp-deps && \
    adduser --disabled-password --no-create-home app

ENV PATH="/py/bin:$PATH"

USER app

下一个是docker-compose文件。在command中指定了wat_for_db,并在本地和容器中都指定了8000端口。在db中使用了postgres:13-alpine。

version: '3.9'

services:
  app:
    build:
      context: .
    command: >
      sh -c "python manage.py wait_for_db &&
             python manage.py migrate &&
             python manage.py runserver 0.0.0.0:8000"
    ports:
      - 8000:8000
    volumes:
      - ./app:/app
    environment:
      - SECRET_KEY=devsecretkey
      - DB_HOST=db
      - DB_NAME=devdb
      - DB_USER=devuser
      - DB_PASS=changeme
    depends_on:
      - db

  db:
    image: postgres:13-alpine
    environment:
      - POSTGRES_DB=devdb
      - POSTGRES_USER=devuser
      - POSTGRES_PASSWORD=changeme

根据 Postgre 的设置,在 requirements.txt 中也添加了以下的 Postgre 驱动程序。

psycopg2>=2.8.6,<2.9

Finally (in Chinese: 最后)

虽然感觉解释还不够详细,不过Django已经成功运行了吗?一旦应用程序运行成功,接下来只需要继续创建应用程序的具体内容。大家辛苦了。另外,感谢大家一直以来阅读完整文章。

bannerAds