Ich wollte eine Anwendung mit einer Djagno + React-Konfiguration entwickeln und für Google Kubernetes Engine bereitstellen, dachte aber nicht, dass es ein zusammenhängendes Tutorial gibt, also habe ich es geschrieben.
** Ich denke, es gibt einige Punkte, die noch nicht perfekt sind **, aber ich denke, wenn Sie ein wenig Erfahrung haben, können Sie sie sofort verwenden.
Dies ist eine Aufzeichnung eines unerfahrenen Hobbyingenieurs, der mit der Bereitstellung zur Erstellung eines Portfolios zu kämpfen hat. Wenn es Mängel gibt, weisen Sie bitte darauf hin. ..
$ 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
#Projektordner erstellen
$ mkdir gke-django-tutorial
$ cd gke-django-tutorial
#Erstellen Sie ein Verzeichnis
$\gke-django-tutorial\mkdir backend
$\gke-django-tutorial\mkdir frontend
Der Backend-Pod liefert die Rest-API mit Django-Rest-Framework. Lassen Sie uns das Innere des Backend-Pods organisieren.
Rolle | Containerbild |
---|---|
Proxyserver | Nginx: 1.17.4-alpine |
Anwendung | Python3.7 - Django Rest Framework |
cloud_sql_proxy | gcr.io/cloudsql-docker/gce-proxy |
Erstellen Sie ein Verzeichnis im Backend.
#Wechseln Sie in das Backend-Verzeichnis
$\gke-django-tutorial\cd backend
#Erstellen eines Django-Verzeichnisses
$\gke-django-tutorial\backend\mkdir web-back
#Erstellen eines Nginx-Verzeichnisses
$\gke-django-tutorial\backend\mkdir nginx
Wir werden eine virtuelle Umgebung für Python erstellen und einen API-Server mit dem Django Rest Framework entwickeln.
Erstellen Sie dies im Verzeichnis backend \ web-back \
.
# web-hinteres Verzeichnis
$\gke-django-tutorial\backend\cd web-back
#Erstellen einer virtuellen Umgebung für Python
$\gke-django-tutorial\backend\web-back\python -m venv venv
#Virtuelle Umgebung aktivieren
$\gke-django-tutorial\backend\web-back\venv\Scripts\activate
#Python-Pakete installieren
(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
#Starten Sie ein Django-Projekt
(venv)$\gke-django-tutorial\backend\web-back\django-admin startproject config .
Durch Ausführen von "django-admin startprject config." Im Web-Back-Verzeichnis Ein Django-Projektordner namens "config" wurde erstellt.
Lassen Sie uns überprüfen, ob der lokale Server gestartet wird.
(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.
Da der Entwicklungsserver gestartet wurde, wird der Bildschirm "Die Installation hat erfolgreich funktioniert!" Angezeigt, indem Sie auf "http: // localhost: 8000 /" zugreifen.
settings.py
Bearbeiten Sie config / settings.py
, um die Grundeinstellungen einzuschließen.
Vertrauliche Informationen in settings.py
sollten in die .env
-Datei geschrieben werden, damit sie nicht weitergegeben werden.
Lassen Sie uns die in .env
beschriebenen Informationen mit dem Paket python-dotenv ändern.
# .Erstellen einer env-Datei
(venv)$\gke-django-tutorial\backend\web-back\type nul > .env
# config/settings.py
import os
from dotenv import load_dotenv #hinzufügen
# 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) #hinzufügen
# .Laden von env
load_dotenv(os.path.join(BASE_DIR, '.env')) #hinzufügen
# 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 = ["*"] #Veränderung
# 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')], #Veränderung
'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' #Veränderung
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/'
#Verweis auf statische Dateien in der Entwicklungsumgebung
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] #hinzufügen
#Verweis auf statische Dateien in der Produktion
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') #hinzufügen
#Mediendateipfad
MEDIA_URL = '/media/' #hinzufügen
.env
# .env
SECRET_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
DEBUG = False
Lassen Sie uns eine Aufgabenanwendung erstellen.
(venv)$\gke-django-tutorial\backend\web-back\python manage.py startapp todo
Fügen Sie "todo" und "rest_framework" zu "INSTALLED_APPS" in "config / settings.py" hinzu.
# 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',
]
#hinzufügen
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
]
}
rest_framework.permissions.AllowAny
dient zum Freigeben der Standardeinstellung'DEFAULT_PERMISSION_CLASSES'
, die implizit von django-rest-framework festgelegt wird.
todo/models.py
Erstellen Sie ein "todo" -Anwendungsmodell.
# 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
Fügen Sie das erstellte Modell zu "todo / admin.py" hinzu.
# todo/admin.py
from django.contrib import admin
from .models import Todo
admin.site.register(Todo)
Wandern.
(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
Erstellen Sie einen Administrator.
(venv)$\gke-django-tutorial\backend\web-back\python manage.py createsuperuser
Nutzername(leave blank to use '[YOUR_NAME]'): [USER_NAME]
Mail Adresse: [email protected]
Password:
Password (again):
Superuser created successfully.
Wenn Sie den Entwicklungsserver starten und auf "http: // localhost: 8000 / admin /" zugreifen, wird der Anmeldebildschirm der Django-Verwaltungssite angezeigt. Geben Sie den festgelegten Benutzernamen und das Kennwort ein, um sich anzumelden.
Wenn Sie sich anmelden können, sehen Sie die Tabelle der erstellten Anwendung "Todo". Fügen wir ein paar Elemente hinzu.
URLs
Fügen Sie dem todo-Applikator in config / urls.py
eine Route hinzu.
# 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')) #hinzufügen
]
todo/urls.py
Erstellen Sie "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
Erstellen Sie einen Serializer, um die Modellinstanz einfach in das JSON-Format zu konvertieren.
(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')
Die id
at fields = ('id', 'title', 'text')
wird von Django automatisch hinzugefügt, wenn Sie im Modell keinen PrimaryKey
angeben.
todo/views.py
Beim Erstellen von views.py
mit dem Django-Rest-Framework erbt es ~~ APIView
von 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
Ich habe den Router usw. noch nicht eingerichtet, bin aber vorerst bereit, die Elemente der Todo-Anwendung als Rest-API bereitzustellen. Sie können die API-Ansicht überprüfen, indem Sie auf dem Entwicklungsserver auf "http: // localhost: 8000 / api /" zugreifen.
Bisher haben wir uns in der lokalen Umgebung entwickelt, die in Django üblich ist.
CORS
Wie Django (localhost: 8000
) mit React ( localhost: 3000
) für json interagiert
Es ist erforderlich, CORS (Cross-Origin Resource Sharing) festzulegen.
Lassen Sie uns django-cors-headers
installieren.
(venv)$\gke-django-tutorial\backend\web-back\python -m pip install django-cors-headers
Aktualisieren Sie 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', #hinzufügen
'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
Angenommen, config / settings.py
wird in der Produktionsumgebung verwendet, erstellen Sie config / local_settings.py
und bewahren Sie es für die lokale Entwicklung auf. Durch die Trennung von settings.py, sodass CloudSQL bei der Bereitstellung von GKE verwendet wird und sqlite3 lokal verwendet wird, müssen die Einstellungswerte nicht neu geschrieben werden.
#Eine Datei erstellen
(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'),
}
}
Starten Sie den Entwicklungsserver mit config / local_settings.py
.
(venv)$\gke-django-tutorial\backend\web-back\python manage.py runserver --settings config.local_settings
Tests
Schreiben Sie einen 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'...
Es scheint funktioniert zu haben.
Aggregieren Sie statische Dateien so, dass das CSS der Administratorfunktion nach der Bereitstellung wiedergegeben wird. Das Verzeichnis, in dem statische Dateien für die Verteilung zusammengefasst werden, lautet "staticfiles /", und das statische Dateiverzeichnis, das für die Entwicklung hinzugefügt wird, lautet "static /".
#Übermittlungsverzeichnis für statische Dateien
(venv)$\gke-django-tutorial\backend\web-back\mkdir staticfiles
#Entwicklungsverzeichnis für statische Dateien
(venv)$\gke-django-tutorial\backend\web-back\mkdir static
#Aggregation statischer Dateien
(venv)$\gke-django-tutorial\backend\web-back\python manage.py collectstatic
Sie können sehen, dass Admin-CSS usw. auch im Verzeichnis staticfiles /
hinzugefügt werden.
Verwenden Sie Cloud SQL Postgres bei der Bereitstellung in GKE. Sie benötigen psycopig2, um Postgres von Django verwenden zu können. Verwenden Sie auch Gunicorn, um die Anwendung zu starten.
Installieren Sie die erforderlichen Pakete zusätzlich und stellen Sie die in der virtuellen Umgebung installierten Python-Pakete in der Datei require.txt zusammen.
#Paketinstallation
(venv)$\gke-django-tutorial\backend\web-back\python -m pip install wheel gunicorn psycopg2-binary
# requirements.Aktualisiere txt
(venv)$\gke-django-tutorial\backend\web-back\python -m pip freeze > requirements.txt
Bei der Ausführung wird die Datei require.txt unter backend / erstellt.
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
Erstellen Sie eine Docker-Datei, um ein Container-Image auf der Django-Seite zu erstellen.
#Erstellen einer Docker-Datei
(venv)$\gke-django-tutorial\backend\web-back\type nul > Dockerfile
# .Docker ignorieren
(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
Erstellen Sie auch einen .dockerignore, um die Dateien zu trennen, die Sie nicht in den Container einfügen möchten.
.dockerignore
venv/
.env
Dockerfile
config/local_settings.py
Jetzt können Sie ein Docker-Image für Django erstellen.
Platzieren Sie den Nginx-Container als Reverse-Proxy-Server im Backend-Pod.
Nginx verwendet die Konfigurationsdatei in / etc / nginx / conf.d /
, um die Reverse-Proxy-Funktionalität zu definieren.
Außerdem möchte ich am Ende der Backend-Entwicklung mit Docker-Compose beginnen. Erstellen Sie daher auch eine Datei für Docker-Compose.
#Datei für Nginx erstellen
$\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
hat den Reverse-Proxy auf Nginx container: 80
⇒ Django: 8000
gesetzt.
Die Anweisung location = / healthz
ist der Pfad für die Integritätsprüfung, den Sie nach der Bereitstellung in GKE benötigen.
Die Anweisung location / static /
ist der Pfad für die Übermittlung statischer Dateien. Ohne dies wird das CSS des Administratorbildschirms nicht angewendet. Bei der Bereitstellung in GKE werden statische Dateien aus dem Cloud-Speicher bereitgestellt. Löschen Sie sie daher.
Die server
-Direktive lautet localhost: 8000
bei der Bereitstellung auf GKE und web-back: 8000
beim Start mit Docker-Compose.
Dies liegt daran, dass beim Starten mit Docker-Compose der Name nach Dienstname aufgelöst werden muss. Bei der Bereitstellung auf GKE befindet es sich im selben Pod, sodass der Name mit "localhost: 8000" aufgelöst werden kann.
; default.dev.conf
upstream django {
server web-back:8000;
}
; default.Für 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;
}
;Wird bei der Bereitstellung von GKE gelöscht
location /static/ {
alias /code/staticfiles/;
}
}
Die Docker-Datei spiegelt die Einstellungen wider, indem die Nginx-Einstellungsdatei in den Nginx-Container kopiert wird.
# 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.Für Entwickler
# COPY default.conf /etc/nginx/conf.d
Ich möchte Docker-Compose verwenden, um einen Container mit einer Nginx + Django-Konfiguration zu starten.
# docker-compose.Erstellen Sie 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.Beginnen Sie mit yml
$\gke-django-tutorial\backend\docker-compose up --build
http: // localhost: 8080
⇒ Nginx-Container: 80
⇒ Django: 8000
Es wird portweitergeleitet.
Gehen Sie zu http: // localhost: 8080 / admin / und überprüfen Sie, ob das CSS wiedergegeben wird.
Die Umgebung ist für die Backend-Entwicklung bereit, indem Sie mit Docker-Compose in der lokalen Umgebung beginnen.
⇒ Gehen Sie zu (2) Frontend-Entwicklung: Nginx + React
Recommended Posts