'Elastic Beanstalk Django 502 Bad Gateway Error
Background
I am currently attempting to deploy a django app on an AWS Elastic Beanstalk Environment on an Amazon Linux 2 Instance. I followed the setup instructions according to the documentation given by Amazon and I also followed other tutorials because AWS did not cover certain key points. I initially faced issues with trying to successfully deploy my Django app to my EB environment but I managed to upload my app. However, the environment now gives me a Severe health status in which when I checked eb.engine.logs I find the following error log
----------------------------------------
/var/log/web.stdout.log
----------------------------------------
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/django/contrib/auth/base_user.py", line 48, in <module>
web: class AbstractBaseUser(models.Model):
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/django/db/models/base.py", line 108, in __new__
web: app_config = apps.get_containing_app_config(module)
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/django/apps/registry.py", line 253, in get_containing_app_config
web: self.check_apps_ready()
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/django/apps/registry.py", line 136, in check_apps_ready
web: raise AppRegistryNotReady("Apps aren't loaded yet.")
web: django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
web: [2022-02-10 14:36:37 +0800] [20685] [INFO] Worker exiting (pid: 20685)
web: [2022-02-10 06:36:37 +0000] [20678] [INFO] Shutting down: Master
web: [2022-02-10 06:36:37 +0000] [20678] [INFO] Reason: Worker failed to boot.
web: [2022-02-10 06:36:38 +0000] [20693] [INFO] Starting gunicorn 19.7.1
web: [2022-02-10 06:36:38 +0000] [20693] [INFO] Listening at: http://127.0.0.1:8000 (20693)
web: [2022-02-10 06:36:38 +0000] [20693] [INFO] Using worker: threads
web: [2022-02-10 06:36:38 +0000] [20700] [INFO] Booting worker with pid: 20700
web: [2022-02-10 14:36:38 +0800] [20700] [ERROR] Exception in worker process
web: Traceback (most recent call last):
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/gunicorn/arbiter.py", line 578, in spawn_worker
web: worker.init_process()
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/gunicorn/workers/gthread.py", line 109, in init_process
web: super(ThreadWorker, self).init_process()
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/gunicorn/workers/base.py", line 126, in init_process
web: self.load_wsgi()
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/gunicorn/workers/base.py", line 135, in load_wsgi
web: self.wsgi = self.app.wsgi()
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
web: self.callable = self.load()
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
web: return self.load_wsgiapp()
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 52, in load_wsgiapp
web: return util.import_app(self.app_uri)
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/gunicorn/util.py", line 352, in import_app
web: __import__(module)
web: File "/var/app/current/strol/wsgi.py", line 16, in <module>
web: import strol.routing as routing
web: File "/var/app/current/strol/routing.py", line 3, in <module>
web: from app.consumers import NoseyConsumer, AssetSocket, CompanySocket
web: File "/var/app/current/app/consumers.py", line 1, in <module>
web: from app.models import CameraReport, Sites, Broadcast, Member, User, BroadcastGroup
web: File "/var/app/current/app/models.py", line 2, in <module>
web: from django.contrib.auth.models import Group, User, AbstractUser
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/django/contrib/auth/models.py", line 3, in <module>
web: from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
web: File "/var/app/venv/staging-LQM1lest/lib/python3.7/site-packages/dj
What I know
My hunch is that I either misconfigured one of my ebextensions file or based on what I see in the log above, I did not start one of my Apps correctly. I say this because my Django App, also uses a websocket i.e. Daphne (i think that's what the dependency is called). So I believe that I may not have correctly configured that. If that's not the problem that can be inferred from this error log then I have no idea.
I hope that everyone can understand that I am only just assigned to deal with deployment and Django isn't really my strength. Thus, I am going to put up some of the key files here for everyone's reference.
requirements.txt
aioredis==1.3.1
asgiref==3.3.4
async-timeout==4.0.2
attrs==21.4.0
autobahn==21.2.1
Automat==20.2.0
CacheControl==0.12.10
cachetools==5.0.0
certifi==2021.5.30
cffi==1.14.5
channels==3.0.4
channels-redis==3.3.1
chardet==4.0.0
charset-normalizer==2.0.11
constantly==15.1.0
cryptography==3.1.1
daphne==3.0.2
dj-database-url==0.4.2
Django==3.2.4
django-cors-headers==3.7.0
django-environ==0.8.1
django-rest-auth==0.9.5
djangorestframework==3.12.4
et-xmlfile==1.1.0
fcm-django==1.0.8
firebase-admin==5.2.0
google-api-core==2.5.0
google-api-python-client==2.36.0
google-auth==2.6.0
google-auth-httplib2==0.1.0
google-cloud-core==2.2.2
google-cloud-firestore==2.3.4
google-cloud-storage==2.1.0
google-crc32c==1.3.0
google-resumable-media==2.2.0
googleapis-common-protos==1.54.0
grpcio==1.43.0
grpcio-status==1.43.0
gunicorn==19.7.1
hiredis==2.0.0
httplib2==0.20.4
hyperlink==21.0.0
idna==2.10
incremental==21.3.0
lml==0.1.0
msgpack==1.0.3
mysqlclient==2.1.0
numpy==1.20.3
opencv-contrib-python==4.5.2.54
openpyxl==3.0.9
packaging==21.3
Pillow==8.2.0
proto-plus==1.20.0
protobuf==3.19.4
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.20
pyexcel-io==0.6.6
pyexcel-xls==0.7.0
pyexcel-xlsx==0.6.0
PyJWT==1.7.1
pyOpenSSL==19.1.0
pyparsing==3.0.7
python-dateutil==2.8.2
pytz==2021.1
pyzbar==0.1.8
qrcode==6.1
requests==2.27.1
rsa==4.8
service-identity==21.1.0
six==1.16.0
sqlparse==0.4.1
sweetify==2.0.0
twilio==6.60.0
Twisted==22.1.0
txaio==21.2.1
typing_extensions==4.0.1
uritemplate==4.1.1
urllib3==1.26.5
whitenoise==3.3.1
xlrd==2.0.1
xlwt==1.3.0
zope.interface==5.4.0
wsgi.py
import os
# from django.core.asgi import get_asgi_application
from django.core.wsgi import get_wsgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import strol.routing as routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'strol.settings')
application = get_wsgi_application()
settings.py
import os
from firebase_admin import initialize_app
import environ
# Initialise environment variables
env = environ.Env()
environ.Env.read_env()
# 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.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*']
MESSAGE_STORAGE = "django.contrib.messages.storage.cookie.CookieStorage"
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_auth',
'rest_framework.authtoken',
'corsheaders',
'sweetify',
'channels',
'channels_redis',
'fcm_django',
'app',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'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',
]
SWEETIFY_SWEETALERT_LIBRARY = 'sweetalert2'
ROOT_URLCONF = 'strol.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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',
],
},
},
]
ASGI_APPLICATION = "strol.asgi.application"
WSGI_APPLICATION = 'strol.wsgi.application'
AUTH_USER_MODEL = 'app.User'
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': env('DB_NAME'),
'USER': env('DB_USER'),
'PASSWORD': env("DB_PASSWORD"),
'HOST': localhost ,
'PORT': '3306',
}
}
CORS_ORIGIN_ALLOW_ALL = True
# Password validation
# https://docs.djangoproject.com/en/2.2/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',
},
]
AUTH_USER_MODEL = 'app.User'
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Asia/Singapore'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'app/static'),
)
LOGIN_URL='/'
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
# 'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
# # Channels
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': [env('REDIS_INSTANCE')],
},
},
}
GOOGLE_APPLICATION_CREDENTIALS = os.path.join(BASE_DIR, env("GOOGLE_APPLICATION_CREDENTIALS"))
FIREBASE_APP = initialize_app()
routing.py
from django.urls.conf import re_path
from django.urls import path
from app.consumers import NoseyConsumer, AssetSocket, CompanySocket
from django.core.asgi import get_asgi_application
websocket_urlpatterns = [
path("app/", NoseyConsumer),
re_path(r"camera/socket/(?P<location_id>\w+)/", AssetSocket.as_asgi()),
re_path(r"company/socket/(?P<company_name>[-\w\s]+)/", CompanySocket.as_asgi()),
]
asgi.py
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'strol.settings')
x = get_asgi_application()
from channels.routing import ProtocolTypeRouter, URLRouter
from routing import websocket_urlpatterns
from channels.auth import AuthMiddlewareStack
application = ProtocolTypeRouter({
"http": x, #http
"websocket":
AuthMiddlewareStack( #websocket
URLRouter(
websocket_urlpatterns
)
),
})
.ebextensions/django.config
option_settings:
aws:elasticbeanstalk:application:environment:
DJANGO_SETTINGS_MODULE: "strol.settings"
PYTHONPATH: "/var/app/current:$PYTHONPATH"
aws:elasticbeanstalk:container:python:
WSGIPath: strol.wsgi:application
aws:elbv2:listener:80:
DefaultProcess: http
ListenerEnabled: 'true'
Protocol: HTTP
Rules: ws
aws:elbv2:listenerrule:ws:
PathPatterns: /ws/*
Process: websocket
Priority: 1
aws:elasticbeanstalk:environment:process:http:
Port: '80'
Protocol: HTTP
aws:elasticbeanstalk:environment:process:websocket:
Port: '5000'
Protocol: HTTP
container_commands:
01_collectstatic:
command: "source /var/app/venv/*/bin/activate && python3 manage.py collectstatic --noinput"
leader_only: true
What I've tried
I've searched far and wide for other posts (including those outside of stackoverflow) with similar issues in which I believe there are and I have seen some of them. Which is why my hunch has been directed to Daphne and the Websocket on my app. Unfortunately, implementing any of the solutions that were given did not seem to work at all on my side. I hope that someone is able to help me with this.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
