Cet article est l'article du 16e jour du Web Crew Advent Calendar 2019. Hier, c'était @ Hideto-Kiyoshima-wc Scala's Option / Either / Try Super Introduction.
Je suis @yagiyuuuu pour la deuxième année depuis que j'ai rejoint Web Crew Co., Ltd. en tant que nouveau diplômé. Actuellement, je développe un environnement d'application de Nginx + uWSGI + Python (Django) en le créant avec Docker. J'ai écrit cet article dans l'espoir qu'il aidera les personnes qui développent des applications avec Django.
Ouvrez le panneau de contrôle, Assurez-vous que "Programmes et fonctionnalités" -> "Activer ou désactiver les fonctionnalités Windows" -> "Hyper-V" est coché. S'il n'est pas coché, vérifiez-le et redémarrez le PC pour l'activer. Ensuite, installez "Docker Desktop pour Windows". Vous pouvez l'installer à partir d'ici (https://docs.docker.com/docker-for-windows/install/).
Ci-dessous, exécutez l'application Django avec la configuration.

Installez python + uWSGI, Nginx sur Alpine.
Créez un conteneur pour Nginx et python + uWSGI. Cette fois, le journal est sorti sous django-sample, mais veuillez le configurer pour qu'il crache le journal où vous le souhaitez.
django-sample/docker-compose.yml
version: '2'
services:
  nginx:
    build: "./Infrastructure/nginx/"
    volumes:
      - ./logs/nginx:/var/log/nginx
    ports:
      - "80:80"
    networks:
      django-sample-network:
        ipv4_address: 172.23.0.4
  python:
    build: "./Infrastructure/python/"
    volumes:
      - ./Application/django-sample:/home/work/django-sample
      - ./logs/django:/home/work/django
      - ./logs/uwsgi:/home/work/uwsgi
    ports:
      - "8000:8000"
    networks:
      django-sample-network:
        ipv4_address: 172.23.0.5
networks:
  django-sample-network:
    driver: bridge
    ipam:
     driver: default
     config:
       - subnet: 172.23.0.0/24
Nginx
django-sample/Infrastructure/nginx/Dockerfile
FROM nginx:1.13.1-alpine
COPY work/nginx.conf /etc/nginx
RUN apk --no-cache add tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    apk del tzdata
CMD ["nginx", "-g", "daemon off;"]
uWSGI
django-sample/Infrastructure/python/Dockerfile
FROM python:3.7
ENV LANG C.UTF-8
ENV TZ Asia/Tokyo
RUN mkdir /home/work
RUN mkdir /home/work/django
RUN mkdir /home/work/uwsgi
COPY work/ /home/work
WORKDIR /home/work
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
CMD ["uwsgi", "--ini", "/home/work/uwsgi.ini"]
django-sample/Infrastructure/nginx/work/nginx.conf
worker_processes auto;
error_log /var/log/nginx/error_app.log;
events {
    worker_connections 1024;
}
http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access_app.log  main;
    sendfile            on;
    tcp_nopush          on;
    keepalive_timeout   120;
    proxy_read_timeout  120;
    proxy_send_timeout  120;
    types_hash_max_size 2048;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    server {
        listen       80 default_server;
        server_name  _;
        fastcgi_read_timeout 60s;
        client_max_body_size 1m;
        location ~ ^/app/ {
            add_header Cache-Control no-cache;
            include uwsgi_params;
            uwsgi_pass 172.23.0.5:8000;
            uwsgi_read_timeout 60s;
        }
    }
}
django-sample/Infrastructure/python/work/uwsgi.ini
[uwsgi]
chdir=/home/work/django-sample
module=django-sample.wsgi
master=True
vacuum=True
max-requests=5000
socket=:8000
py-autoreload=1
logto=/home/work/uwsgi/django-app.log
buffer-size=10240
log-format=%(addr) - %(user) [%(ltime)] "%(method) %(uri) %(proto)" %(status) %(size)`` "%(referer)" "%(uagent)"
django-sample/Infrastructure/python/work/requirements.txt
django==2.2
uwsgi==2.0.17.1
Décrivez le module que vous souhaitez installer dans requirements.txt.
django-sample/.env
COMPOSE_FILE=docker-compose.yml
Puisque nous nous concentrons sur la création d'applications ici, Pour plus d'informations sur l'application Django, veuillez consulter le site officiel. Aussi, n'écrivez pas de code dans «__init __. Py» et «pycache», mais créez-les. S'il n'est pas créé, l'application ne fonctionnera pas.
django-sample/Application/django-sample/manage.py
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django-sample.settings")
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)
django-sample/Application/django-sample/django-sample/settings.py
"""
Django settings for django-sample project.
Generated by 'django-admin startproject' using Django 2.0.3.
For more information on this file, see
https://docs.djangoproject.com/en/2.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.0/ref/settings/
"""
import os
import json
import traceback
#Spécifiez le gestionnaire utilisé pour la sortie du journal
LOG_HANDLER = ["app"]
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'ekf!&30u3&idt-qr3250(t+j#%@(vyxr02c-7fj!a81$!)#q=('
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
#Définissez l'adresse IP et le domaine du serveur qui autorise la connexion
#Hôte local si rien n'est défini(localhost)Connexion possible uniquement depuis
ALLOWED_HOSTS = ["localhost"]
# Application definition
#Ajout de "app". Si vous ne l'ajoutez pas, les balises personnalisées définies dans les balises de modèle ne seront pas reconnues.
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app',
]
ROOT_URLCONF = 'django-sample.urls'
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(BASE_DIR, 'templates'),
        ],
        'APP_DIRS': True,
        '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',
            ],
        },
    },
]
WSGI_APPLICATION = 'django-sample.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
# Password validation
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]
# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/
#LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'ja'
#TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Tokyo'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_URL = ''
LOGGING = {
    'version': 1,
    'formatters': {
        'app': {
            'format': '%(asctime)s [%(levelname)s] %(pathname)s:%(lineno)d %(message)s'
        }
    },
    'handlers': {
        'app': {
            'level': 'DEBUG',
            'class': 'logging.handlers.TimedRotatingFileHandler',
            'filename': '/home/work/django/app.log',
            'formatter': 'app',
            'when': 'D',        #L'unité D est le jour
            'interval': 1,      #Précisez tous les quelques jours
            'backupCount': 30,  #Nombre de générations de sauvegarde
        }
    },
    'loggers': {
        'django': {
            'handlers': ['app'],
            'level': 'DEBUG',
            'propagate': True,
        },
        'django.server': {
            'handlers': ['app'],
            'level': 'DEBUG',
            'propagate': True,
        },
        'app': {
            'handlers': LOG_HANDLER,
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}
#Paramètres du moteur de session
#Utiliser une session avec des cookies
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
#Date d'expiration de l'état de connexion (secondes)
#Vous pouvez rester connecté jusqu'à ce que la date d'expiration (secondes) spécifiée ici soit dépassée.
#La date d'expiration de la session elle-même est SESSION_COOKIE_AGE
# 8h * 60m * 60s
LOGIN_LIMIT = 28800
#Durée de vie de la session(Secondes)
#Si vous souhaitez modifier la période de validité de la session pour chaque utilisateur, demandez.session.set_expiry(value)Utilisation
SESSION_COOKIE_AGE = 1800
django-sample/Application/django-sample/django-sample/urls.py
"""django-sample URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.urls import path, include
urlpatterns = [
    path('app/', include("app.urls")),
]
django-sample/Application/django-sample/django-sample/wsgi.py
"""
WSGI config for django-sample project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django-sample.settings")
application = get_wsgi_application()
Créez une application dans le projet django sample.
django-sample/Application/django-sample/app/urls.py
from django.urls import path
from app.views.login import view as login_view
urlpatterns = [
    path("", login_view.top, name="login_top")
]
django-sample/Application/django-sample/app/views/login/view.py
from django.http import HttpResponse
from django.http.request import HttpRequest
from django.template import loader
def top(request: HttpRequest):
    template = loader.get_template("login/index.html")
    return HttpResponse(template.render({}, request))
django-sample/Application/django-sample/templates/login/index.html
Hello Django!!
Tapez la commande suivante dans la hiérarchie où se trouve docker-compose.yml
$ docker-compose up --build -d
Peut être démarré en arrière-plan en ajoutant -d
$ docker-compose ps
$ docker-compose down
Après avoir démarré le conteneur, allez sur http: // localhost / app /
«Hello Django !!» s'affiche
Veuillez créer votre propre environnement lors de la création d'applications Django! !!
L'article de demain est @ yuko-tsutsui. Je vous remercie.
Recommended Posts