Je voulais développer une application avec la configuration Djagno + React et la déployer sur Google Kubernetes Engine, mais je ne pensais pas qu'il y avait un tutoriel cohérent, alors je l'ai écrit.
Cependant, ** je pense qu'il y a des points qui ne sont pas encore parfaits **, mais je pense que si vous avez un peu d'expérience, vous pouvez l'utiliser immédiatement.
Il s'agit d'un enregistrement d'un ingénieur amateur inexpérimenté qui lutte avec le déploiement pour créer un portefeuille. S'il y a des lacunes, veuillez les signaler. ..
$ node --version
v12.14.1
$ npm --version
6.13.7
$ python --version
Python 3.7.4
$ docker --version
Docker version 19.03.8
OS windows10 pro
#Créer un dossier de projet
$ mkdir gke-django-tutorial
$ cd gke-django-tutorial
#Créer un annuaire
$\gke-django-tutorial\mkdir backend
$\gke-django-tutorial\mkdir frontend
Le pod backend fournit l'API Rest avec Django-rest-framework. Organisons l'intérieur du pod backend.
Rôle | Image du conteneur |
---|---|
Serveur proxy | Nginx: 1.17.4-alpine |
Application | Python3.7 - Framework Rest de Django |
cloud_sql_proxy | gcr.io/cloudsql-docker/gce-proxy |
Créez un répertoire dans le backend.
#Déplacer vers le répertoire backend
$\gke-django-tutorial\cd backend
#Créer un répertoire django
$\gke-django-tutorial\backend\mkdir web-back
#Créer un répertoire Nginx
$\gke-django-tutorial\backend\mkdir nginx
Nous allons créer un environnement virtuel pour Python et développer un serveur API avec le framework Rest Django.
Créez-le dans le répertoire backend \ web-back \
.
# web-retour répertoire
$\gke-django-tutorial\backend\cd web-back
#Créer un environnement virtuel pour Python
$\gke-django-tutorial\backend\web-back\python -m venv venv
#Activer l'environnement virtuel
$\gke-django-tutorial\backend\web-back\venv\Scripts\activate
#Installer des packages Python
(venv)$\gke-django-tutorial\backend\web-back\python -m install --upgrade pip setuptools
(venv)$\gke-django-tutorial\backend\web-back\python -m install django djangorestframework python-dotenv
#Démarrer un projet Django
(venv)$\gke-django-tutorial\backend\web-back\django-admin startproject config .
En faisant django-admin startprject config .
sous le répertoire web-back
Un dossier de projet Django appelé config
a été créé.
Vérifions si le serveur local démarre.
(venv)$\gke-django-tutorial\backend\web-back\python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 17 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.
April 27, 2020 - 11:22:06
Django version 3.0.5, using settings 'config.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
Depuis le démarrage du serveur de développement, vous pouvez voir l'écran de L'installation a fonctionné avec succès!
En accédant à http: // localhost: 8000 /
.
settings.py
Modifiez config / settings.py
pour inclure les paramètres de base.
Les informations confidentielles dans settings.py
doivent être écrites dans le fichier .env
afin qu'elles ne soient pas divulguées.
Modifions-le pour utiliser les informations décrites dans .env
en utilisant le paquet python-dotenv.
# .Créer un fichier env
(venv)$\gke-django-tutorial\backend\web-back\type nul > .env
# config/settings.py
import os
from dotenv import load_dotenv #ajouter à
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_DIR = os.path.basename(BASE_DIR) #ajouter à
# .Chargement env
load_dotenv(os.path.join(BASE_DIR, '.env')) #ajouter à
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = os.getenv('DEBUG')
ALLOWED_HOSTS = ["*"] #Changement
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'config.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], #Changement
'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 = 'config.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.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/3.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/3.0/topics/i18n/
LANGUAGE_CODE = 'ja' #Changement
TIME_ZONE = 'Asia/Tokyo'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
STATIC_URL = '/static/'
#Où faire référence aux fichiers statiques dans l'environnement de développement
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] #ajouter à
#Où référencer les fichiers statiques en production
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') #ajouter à
#Chemin du fichier multimédia
MEDIA_URL = '/media/' #ajouter à
.env
# .env
SECRET_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
DEBUG = False
Créons une application todo.
(venv)$\gke-django-tutorial\backend\web-back\python manage.py startapp todo
Ajoutez todo
et rest_framework
à ʻINSTALLED_APPS dans
config / settings.py`.
# config/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 3rd party
'rest_framework',
# Local
'todo.apps.TodoConfig',
]
#ajouter à
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
]
}
rest_framework.permissions.AllowAny
sert à libérer le paramètre par défaut'DEFAULT_PERMISSION_CLASSES'
défini implicitement par django-rest-framework.
todo/models.py
Créez un modèle d'application «todo».
# todo/models.py
from django.db import models
class Todo(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
def __str__(self):
return self.title
Ajoutez le modèle créé à todo / admin.py
.
# todo/admin.py
from django.contrib import admin
from .models import Todo
admin.site.register(Todo)
Émigrer.
(venv)$\gke-django-tutorial\backend\web-back\python manage.py makemigrations
Migrations for 'todo':
todo\migrations\0001_initial.py
- Create model Todo
(venv)$\gke-django-tutorial\backend\web-back\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 sessions.0001_initial... OK
Applying todo.0001_initial... OK
createsuperuser
Créez un utilisateur administrateur.
(venv)$\gke-django-tutorial\backend\web-back\python manage.py createsuperuser
Nom d'utilisateur(leave blank to use '[YOUR_NAME]'): [USER_NAME]
adresse mail: [email protected]
Password:
Password (again):
Superuser created successfully.
Lorsque vous démarrez le serveur de développement et accédez à http: // localhost: 8000 / admin /
, l'écran de connexion au site d'administration de Django s'affiche. Saisissez le nom d'utilisateur et le mot de passe définis pour vous connecter.
Si vous pouvez vous connecter, vous pouvez voir le tableau de l'application créée Todo
.
Ajoutons quelques éléments.
URLs
Ajoutez une route à l'applicateur de todo dans config / urls.py
.
# config/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('todo.urls')) #ajouter à
]
todo/urls.py
Créez todo / urls.py
.
(venv)$\gke-django-tutorial\backend\web-back\type nul > todo\urls.py
# todo/urls.py
from django.urls import path, include
from .views import ListTodo, DetailTodo
urlpatterns = [
path('<int:pk>/', DetailTodo.as_view()),
path('', ListTodo.as_view())
]
todo/selializers.py
Créez un sérialiseur pour convertir facilement l'instance de modèle au format json.
(venv)$\gke-django-tutorial\backend\type nul > todo\serializers.py
# todo/serializers.py
from rest_framework import serializers
from .models import Todo
class TodoSerializer(serizers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'title', 'body')
ʻId at
fields = ('id', 'title', 'text') ʻest automatiquement ajouté par Django si vous ne spécifiez pas PrimaryKey
dans le modèle.
todo/views.py
Lors de la création de views.py
avec Django rest framework, il hérite ~~ APIView
de rest_framework.generics
.
# todo/views.py
from django.shortcuts import render
from rest_framework import generics
from .models import Todo
from .serializers import TodoSerializer
class ListTodo(generics.ListAPIView):
queryset = Todo.objects.all()
serializer_class = TodoSerializer
class DetailTodo(generics.RetrieveAPIView):
queryset = Todo.objects.all()
serializer_class = TodoSerializer
Je n'ai pas configuré le routeur, etc., mais pour le moment, je suis prêt à fournir les éléments de l'application Todo en tant qu'API Rest.
Vous pouvez vérifier la vue API en accédant à http: // localhost: 8000 / api /
sur le serveur de développement.
Jusqu'à présent, nous nous sommes développés dans l'environnement local, ce qui est courant à Django.
CORS
Comment Django (localhost: 8000
) interagit avec React ( localhost: 3000
) pour json
Il est nécessaire de définir CORS (Cross-Origin Resource Sharing).
Installons django-cors-headers
.
(venv)$\gke-django-tutorial\backend\web-back\python -m pip install django-cors-headers
Mettez à jour config / settings.py
.
# config/settings.py
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 3rd party
'rest_framework',
'corsheaders',
# Local
'todos.apps.TodosConfig',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMidddleware', #ajouter à
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
##################
# rest_framework #
##################
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
]
}
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000',
)
local_settings.py
En supposant que config / settings.py
sera utilisé dans l'environnement de production, créez config / local_settings.py
et conservez-le pour le développement local. En séparant settings.py afin que CloudSQL soit utilisé lors du déploiement de GKE et sqlite3 soit utilisé localement, il n'est pas nécessaire de réécrire les valeurs des paramètres.
#Créer un fichier
(venv)$\gke-django-tutorial\backend\web-back\type nul > config/local_settings.py
# config/local_settings.py
from .settings import *
DEBUG = True
ALLOWED_HOSTS = ['*']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
Démarrez le serveur de développement en utilisant config / local_settings.py
.
(venv)$\gke-django-tutorial\backend\web-back\python manage.py runserver --settings config.local_settings
Tests
Écrivez un test.
# todos/test.py
from django.test import TestCase
from .models import Todo
class TodoModelTest(TestCase):
@classmethod
def setUpTestData(cls):
Todo.objects.create(title="first todo", body="a body here")
def test_title_content(self):
todo = Todo.objects.get(id=1)
excepted_object_name = f'{todo.title}'
self.assertEqual(excepted_object_name, 'first todo')
def test_body_content(self):
todo = Todo.objects.get(id=1)
excepted_object_name = f'{todo.body}'
self.assertEqual(excepted_object_name, 'a body here')
(venv)$\gke-django-tutorial\backend\web-back\python manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..
----------------------------------------------------------------------
Ran 2 tests in 0.007s
OK
Destroying test database for alias 'default'...
Cela semble avoir fonctionné.
Regroupez les fichiers statiques afin que le css de la fonction d'administrateur soit reflété après le déploiement.
Le répertoire qui regroupe les fichiers statiques pour la distribution est staticfiles /
, et le répertoire de fichiers statiques qui est ajouté pour le développement est static /
.
#Répertoire de livraison de fichiers statiques
(venv)$\gke-django-tutorial\backend\web-back\mkdir staticfiles
#Répertoire de développement de fichiers statiques
(venv)$\gke-django-tutorial\backend\web-back\mkdir static
#Agrégation de fichiers statiques
(venv)$\gke-django-tutorial\backend\web-back\python manage.py collectstatic
Vous pouvez voir que le CSS admin etc. est également ajouté sous le répertoire staticfiles /
.
Utilisez Cloud SQL Postgres lors du déploiement sur GKE. Vous avez besoin de psycopig2 pour utiliser Postgres de Django. Utilisez également gunicorn pour lancer l'application.
Installez les packages requis en plus et rassemblez les packages Python installés dans l'environnement virtuel dans requirements.txt.
#Installation du package
(venv)$\gke-django-tutorial\backend\web-back\python -m pip install wheel gunicorn psycopg2-binary
# requirements.Mettre à jour txt
(venv)$\gke-django-tutorial\backend\web-back\python -m pip freeze > requirements.txt
Une fois exécuté, requirements.txt sera créé sous backend /.
asgiref==3.2.7
Django==3.0.5
django-cors-headers==3.2.1
djangorestframework==3.11.0
gunicorn==20.0.4
psycopg2-binary==2.8.5
python-dotenv==0.13.0
pytz==2019.3
sqlparse==0.3.1
Créez un Dockerfile pour créer une image de conteneur côté Django.
#Créer un Dockerfile
(venv)$\gke-django-tutorial\backend\web-back\type nul > Dockerfile
# .Création de docker ignore
(venv)$\gke-django-tutorial\backend\web-back\type nul > .dockerignore
# backend/web-back/Dockerfile
# set base image
FROM python:3.7
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# set work directory
WORKDIR /code
# install dependencies
COPY requirements.txt ./
RUN python3 -m pip install --upgrade pip setuptools
RUN pip install -r requirements.txt
# Copy project
COPY . ./
# Expose application port
EXPOSE 8000
Créez également un .dockerignore pour séparer les fichiers que vous ne souhaitez pas placer dans le conteneur.
.dockerignore
venv/
.env
Dockerfile
config/local_settings.py
Vous êtes maintenant prêt à créer une image Docker pour Django.
Placez le conteneur Nginx en tant que serveur proxy inverse dans le backend-Pod.
Nginx utilise le fichier de configuration dans / etc / nginx / conf.d /
pour définir la fonctionnalité de proxy inverse.
De plus, à la fin du développement du backend, je voudrais le démarrer avec docker-compose, donc créez également un fichier pour docker-compose.
#Créer un fichier pour Nginx
$\gke-django-tutorial\backened\nginx\type nul > Dockerfile
$\gke-django-tutorial\backened\nginx\type nul > Dockerfile.dev
$\gke-django-tutorial\backened\nginx\type nul > default.conf
$\gke-django-tutorial\backened\nginx\type nul > default.dev.conf
default.conf
a défini le proxy inverse comme Conteneur Nginx: 80
⇒ Django: 8000
.
La directive location = / healthz
est le chemin de vérification de l'état dont vous aurez besoin après le déploiement sur GKE.
La directive location / static /
est le chemin d'accès aux fichiers statiques. Sans cela, le CSS de l'écran administrateur ne sera pas appliqué. Lors du déploiement sur GKE, les fichiers statiques seront fournis à partir de Cloud Storage, supprimez-les donc.
La directive server
est localhost: 8000
lors du déploiement sur GKE et web-back: 8000
lors du démarrage avec docker-compose.
En effet, lorsque vous démarrez avec docker-compose, il est nécessaire de résoudre le nom par nom de service. Lors du déploiement sur GKE, il se trouve dans le même pod, de sorte que le nom peut être résolu avec localhost: 8000
.
; default.dev.conf
upstream django {
server web-back:8000;
}
; default.Pour conf
; upstream django {
; server localhost:8000;
; }
server {
listen 80;
location = /healthz {
return 200;
}
location / {
proxy_pass http://django;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
}
;Supprimé lors du déploiement de GKE
location /static/ {
alias /code/staticfiles/;
}
}
Le Dockerfile reflète les paramètres en copiant le fichier de paramètres Nginx dans le conteneur Nginx.
# backend\nginx\Dockerfile.dev
FROM nginx:1.17.4-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY default.dev.conf /etc/nginx/conf.d
# backend\nginx\Dockerfile.Pour dev
# COPY default.conf /etc/nginx/conf.d
Je voudrais utiliser docker-compose pour lancer un conteneur avec une configuration Nginx + Django.
# docker-compose.Créer yml
$\gke-django-tutorial\backend\type nul > docker-compose.yml
version: "3.7"
services:
web-back:
container_name: python-backend
env_file: ./web-back/.env
build: ./web-back/.
volumes:
- ./web-back:/code/
- static_volume:/code/staticfiles # <-- bind the static volume
stdin_open: true
tty: true
command: gunicorn --bind :8000 config.wsgi:application
networks:
- backend_network
environment:
- CHOKIDAR_USEPOLLING=true
- DJANGO_SETTINGS_MODULE=config.local_settings
server:
container_name: nginx
build:
context: ./nginx/.
dockerfile: Dockerfile.dev
volumes:
- static_volume:/code/staticfiles # <-- bind the static volume
ports:
- "8080:80"
depends_on:
- web-back
networks:
- backend_network
networks:
backend_network:
driver: bridge
volumes:
static_volume:
# docker-compose.Commencez avec yml
$\gke-django-tutorial\backend\docker-compose up --build
http: // localhost: 8080
⇒ Conteneur Nginx: 80
⇒ Django: 8000
Il est transféré par port.
Allez sur http: // localhost: 8080 / admin /
et vérifiez si le CSS est reflété.
L'environnement est prêt pour le développement backend en commençant par docker-compose dans l'environnement local.
⇒ Accédez à (2) Développement Frontend: Nginx + React
Recommended Posts