Докеризация приложения на основе Django с помощью Postgres + Redis + ElasticSearch

Docker — прекрасный инструмент для контейнеризации вашего сайта. На веб-сайте есть много микросервисов, которые в большинстве случаев взаимозависимы. Все становится еще хуже, когда мы пытаемся настроить наше приложение на другом ПК / операционной системе. Docker спасает в этой ситуации и решает очень популярную проблему, с которой сталкивается почти каждый программист при переносе кода на другую платформу.

4WwcmWUBCXmZ4iV0J_esaqE7O_GVYjON52dbVkEv5_c-2849584195.jpg

🚧 Прежде чем двигаться дальше, вы должны иметь базовые знания о Docker и Docker Compose.

Здесь я собираюсь использовать свое уже созданное приложение на основе django. Фильм Апи который использует Postgres, Redis и ElasticSearch.

Я буду использовать файл компоновки Docker, чтобы держать каждую службу в порядке, поскольку мы можем запустить наш сервер django только после того, как postgres будет готов, и мы можем запустить эластичный поиск только после того, как будет готов Redis. так что эти сервисы взаимозависимы, и я собираюсь связать их правильно, чтобы они могли запускаться по порядку, а не просто работать независимо и ломать что-то.

Прежде чем я начну объяснять, взгляните на мой последний компоновочный файл Docker.

AwLookGIF.gif

version: '3.8' services: django_server: build: . working_dir: /usr/src/app command: > sh -c "python manage.py wait_for_db && python manage.py wait_for_elk && python manage.py migrate && apt install -y curl && echo 'sending curl to Elastic hosts' && curl -X GET ${ELK_CONNECTION_PROTOCOL}://${ELK_HOST}:${ELK_PORT} && python manage.py generate_test_data 1000 && gunicorn src.wsgi:application --bind 0.0.0.0:8000" ports: - 8000:8000 env_file: .env depends_on: - elasticsearch7 - postgresql_db container_name: django_server elasticsearch7: image: elasticsearch:7.17.5 ports: - ${ELK_PORT}:${ELK_PORT} - 9300:9300 container_name: ${ELK_HOST} restart: always environment: - discovery.type=single-node - node.name=django_flix - "ES_JAVA_OPTS=-Xms512m -Xmx512m" postgresql_db: image: postgres ports: - 5432:5432
    restart: always
    env_file: .env
    container_name: ${POSTGRES_HOST}

В приведенном выше коде я добавил depends_on чтобы службы ждали другую перед запуском. У меня не очень хорошее понимание докера, поэтому я не знаю, почему сервер django всегда запускается еще до полного запуска зависимых служб. Итак, чтобы решить эту проблему, я сделал пользовательскую команду в django, которая останавливает сервер до тех пор, пока база данных и ElasticSearch не будут полностью запущены.

вот код для обоих файлов, где я пишу пользовательские команды.

"""
Django Command to wait for DB to be available
"""
import time from django.core.management import BaseCommand
from django.db.utils import OperationalError as DjangoDbUtilsOperationalError
from psycopg2 import OperationalError as Psycopg2OperationalError class Command(BaseCommand): """Django command to pause execution until database is available""" def handle(self, *args, **options): self.stdout.write("Waiting for database...") db_is_up = False while not db_is_up: try: self.check(databases=["default"]) db_is_up = True self.stdout.write(self.style.SUCCESS("Database is available")) except (Psycopg2OperationalError, DjangoDbUtilsOperationalError): self.stdout.write( self.style.WARNING( "Database is still not ready. will try in 1 second" ) ) time.sleep(1)

А этот ниже предназначен для ожидания начала эластичного поиска.

"""
Django Command to wait for DB to be available
"""
import time from django.conf import settings
from django.core.management import BaseCommand
from elasticsearch import Elasticsearch class Command(BaseCommand): """Django command to pause execution until database is available""" def handle(self, *args, **options): self.stdout.write("Waiting for ElasticSearch...") elk_is_up = False host = settings.ELK_HOST port = settings.ELK_PORT while not elk_is_up: try: self.stdout.write( self.style.WARNING( "trying to connect with elk at {}:{}".format(host, port) ) ) es = Elasticsearch([{"host": host, "port": port}]) es.cluster.health(wait_for_status="yellow", request_timeout=1) self.stdout.write(self.style.SUCCESS("✅ ElasticSearch is available")) elk_is_up = True except Exception: self.stdout.write( self.style.WARNING( "❌ ElasticSearch is still not ready. will try in 5 second" ) ) time.sleep(5)

Я также использую файл среды, чтобы я мог передавать эти значения в файл компоновки докеров вместо того, чтобы определять их в паре ключ-значение в файле компоновки докеров.

export DEBUG=1
export POSTGRES_DB="postgres"
export POSTGRES_USER="postgres"
export POSTGRES_PASSWORD="postgres"
export POSTGRES_HOST="postgresql_db_latest"
export POSTGRES_PORT=5432
export ES_JAVA_OPTS="-Xms8g -Xmx8g"
export ELK_HOST="elasticsearch_v7"
export ELK_PORT="9200"
export ELK_INDEX_NAME="django_flix"
export ELK_CONNECTION_PROTOCOL="http"

Таким образом, я смог связать эти службы и запустить их по порядку.

Полезные ссылки

Отказ от ответственности — я не эксперт и все еще учусь. Таким образом, могут быть некоторые вещи, которые я мог пропустить или которые могут быть неправильно объяснены. Как только я получу какой-либо комментарий об ошибках или где-то выясню, я исправлю это в блоге.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *