Dockerized Django Application Deployed to AWS Elastic Beanstalk Flushes Database Everytime I Rebuild My Environment. Как мне сохранить БД?

Я развернул django-приложение с помощью docker на AWS Elastic Beanstalk, которое подключено к базе данных AWS RDS postgresql. Каждый раз, когда я обновляю свой код и перестраиваю образ docker, база данных всегда стирается. Я использую github actions для развертывания приложения каждый раз, когда я продвигаю свой код. Я хочу, чтобы база данных сохранялась, как мне это сделать?

После поиска похожих проблем большинство людей предположили, что в одном из сценариев развертывания может быть команда flush. Это не так в моих сценариях развертывания, потому что я никогда явно не промываю базу данных.

Github Actions Config

name: Staging Docker Image CI

on:
  push:
    branches: [ staging ]
  pull_request:
    branches: [ staging ]

jobs:

  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
      with:
        lfs: 'true'
    - 
      name: Build the Docker image
      run: docker build -t scrims -f Dockerfile .
    -
      name: Generate Deployment Package
      run: zip -r deploy.zip *
    -
      name: Get timestamp
      uses: gerred/actions/current-time@master
      id: current-time
        
    - name: Run string replace
      uses: frabert/replace-string-action@master
      id: format-time
      with:
        pattern: '[:\.]+'
        string: "${{ steps.current-time.outputs.time }}"
        replace-with: '-'
        flags: 'g'

    - name: Deploy to EB
      uses: einaregilsson/beanstalk-deploy@v14
      with:
        aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        application_name: scrims
        environment_name: scrims-env-staging
        version_label: "scrims-staging-${{ steps.format-time.outputs.replaced }}"
        region: ap-southeast-1
        deployment_package: deploy.zip

Dockerfile

# syntax=docker/dockerfile:1
FROM python:3.8-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /code
COPY requirements.txt /code/

RUN apt-get update
RUN apt-get -y install libpq-dev gcc
RUN pip3 install -r requirements.txt --no-cache-dir

COPY . /code/

docker-compose.yml

version: "3.9"

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: >
      sh -c "python3 manage.py collectstatic --noinput &&
             python3 manage.py migrate &&
             python3 manage.py ensure_admin &&
             python3 manage.py runserver 0.0.0.0:8000"
    volumes:
      - .:/code
    ports:
      - "80:8000"

Конфигурация базы данных Elastic Beanstalk

Подключение к среде/базе данных

"База данных пары"

Политика удаления базы данных

"Создать моментальный снимок"

Конфигурация базы данных в Django settings.py


if 'RDS_HOSTNAME' in os.environ:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': os.environ['RDS_DB_NAME'],
            'USER': os.environ['RDS_USERNAME'],
            'PASSWORD': os.environ['RDS_PASSWORD'],
            'HOST': os.environ['RDS_HOSTNAME'],
            'PORT': os.environ['RDS_PORT'],
        }
    }
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': os.getenv("POSTGRES_DB"),
            'USER': os.getenv("POSTGRES_USER"),
            'PASSWORD': os.getenv("POSTGRES_PASSWORD"),
            'HOST': 'localhost' if ENVIRONMENT == 'local' else 'db'
        }
    }

Django Custom Command (ensure_admin)

from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand
import os

class Command(BaseCommand):
  help = "Creates an admin user non-interactively if it doesn't exist"

  def handle(self, *args, **options):
    username = os.getenv("DJANGO_SUPERUSER_USERNAME")
    email = os.getenv("DJANGO_SUPERUSER_EMAIL")
    password = os.getenv("DJANGO_SUPERUSER_PASSWORD")
    discord_id = os.getenv("DJANGO_SUPERUSER_DISCORD_ID")

    User = get_user_model()
    if not User.objects.filter(username=username).exists():
      User.objects.create_superuser(
        username=username,
        email=email,
        discord_id=discord_id,
        password=password
      )
    else:
      admin = User.objects.get(username=username)
      admin.email = email
      admin.password = password
      admin.discord_id = discord_id
      admin.save()

Спасибо за помощь.

Вернуться на верх