Deploying Django & React app in Azure failing to load

I have built an app with an Django back-end, a React front-end and a Postgres database, and I am in the process of deploying them to Azure for the first time.

Key actions I have taken:

  • used django-webpack-loader and webpack-bundle-tracker, so my front and back-end code can be deployed as one app
  • set up Django app in Azure using the App service
  • migrated my postgres database into Azure using the Azure Database for PostgreSQL flexible server

Current outputs:

  • deployed code successfully using github continuous deployment
  • set my database, allowed_hosts, secreet_key and port values in application settings
  • successfully migrated my django folders into the Azure environment using the Web SSH in the Azure portal

My issue:

When I visit my url, the page times out, with 'Application Error'. I'm troubleshooting the error in the logs, which return the output below.

I have noticed two potential errors:

  1. Within the error logs - TypeError: expected str, bytes or os.PathLike object, not PosixPath
  2. When I run python manage.py runserver in the SSH, it returns 'port 8000 is already in use'. After killing and exiting processes on that port, it still remains. I am able to access the server when I run python manage.py runserver 9000, but still get no results.

Azure Error logs:

/home/LogFiles/2023_01_20_lw0sdlwk0000X9_default_docker.log  (https://-test.scm.azurewebsites.net/api/vfs/LogFiles/2023_01_20_lw0sdlwk0000X9_default_docker.log)
2023-01-20T10:10:15.109452667Z   File "<frozen importlib._bootstrap_external>", line 850, in exec_module
2023-01-20T10:10:15.109456467Z   File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
2023-01-20T10:10:15.109460067Z   File "/tmp/8dafa589514f05f/project/settings.py", line 94, in <module>
2023-01-20T10:10:15.109463967Z     'DIRS': [os.path.join(BASE_DIR, 'client')
2023-01-20T10:10:15.109467367Z   File "/opt/python/3.9.7/lib/python3.9/posixpath.py", line 76, in join
2023-01-20T10:10:15.109471167Z     a = os.fspath(a)
2023-01-20T10:10:15.109474567Z TypeError: expected str, bytes or os.PathLike object, not PosixPath
2023-01-20T10:10:15.109478267Z [2023-01-20 10:10:15 +0000] [122] [INFO] Worker exiting (pid: 122)
2023-01-20T10:10:15.227401497Z mkdir() got an unexpected keyword argument 'exist_ok'
/home/LogFiles/2023_01_20_lw0sdlwk0000X9_docker.log  (https://-test.scm.azurewebsites.net/api/vfs/LogFiles/2023_01_20_lw0sdlwk0000X9_docker.log)
2023-01-20T10:05:20.883Z INFO  - Stopping site -test because it failed during startup.
2023-01-20T10:09:33.036Z INFO  - Starting container for site
2023-01-20T10:09:33.037Z INFO  - docker run -d --expose=8000 --name-test_1_547d9150 -e WEBSITES_PORT=8000 -e WEBSITE_SITE_NAME=-test -e WEBSITE_AUTH_ENABLED=False -e PORT=8000 -e WEBSITE_ROLE_INSTANCE_ID=0 -e WEBSITE_HOSTNAME=-test.azurewebsites.net -e WEBSITE_INSTANCE_ID=xyz -e HTTP_LOGGING_ENABLED=1 -e WEBSITE_USE_DIAGNOSTIC_SERVER=True appsvc/python:3.9_20221128.12.tuxprod
2023-01-20T10:09:36.544Z INFO  - Initiating warmup request to container-test_1_547d9150 for site-test
2023-01-20T10:09:52.315Z INFO  - Waiting for response to warmup request for container -test_1_547d9150. Elapsed time = 15.7713165 sec
2023-01-20T10:10:08.131Z INFO  - Waiting for response to warmup request for container -test_1_547d9150. Elapsed time = 31.5870197 sec
2023-01-20T10:13:47.693Z ERROR - Container -test_1_547d9150 for site-test did not start within expected time limit. Elapsed time = 251.1494362 sec
2023-01-20T10:13:47.733Z ERROR - Container -test_1_547d9150 didn't respond to HTTP pings on port: 8000, failing site start. See container logs for debugging.
2023-01-20T10:13:47.753Z INFO  - Stopping site -test because it failed during startup.
/home/LogFiles/AppServiceAppLogs_Feature_Installer/startup_0.log  (https://-test.scm.azurewebsites.net/api/vfs/LogFiles/AppServiceAppLogs_Feature_Installer/startup_0.log)
2023-01-20 09:45:55,527  [Thread-1  ] [DEBUG] : Did not find any previously bound socket
2023-01-20 09:55:42,312  [MainThread] [DEBUG] : Initializating AppServiceAppLogging
2023-01-20 09:55:42,316  [MainThread] [DEBUG] : Initialized AppServiceAppLogging
2023-01-20 09:55:42,359  [Thread-1  ] [DEBUG] : Did not find any previously bound socket
2023-01-20 10:05:11,655  [MainThread] [DEBUG] : Initializating AppServiceAppLogging
2023-01-20 10:05:11,658  [MainThread] [DEBUG] : Initialized AppServiceAppLogging
2023-01-20 10:05:11,706  [Thread-1  ] [DEBUG] : Did not find any previously bound socket
2023-01-20 10:10:08,028  [MainThread] [DEBUG] : Initializating AppServiceAppLogging
2023-01-20 10:10:08,030  [MainThread] [DEBUG] : Initialized AppServiceAppLogging
2023-01-20 10:10:08,039  [Thread-1  ] [DEBUG] : Did not find any previously bound socket

Django Settings.py file:

from pathlib import Path
import environ
import os

env = environ.Env()

environ.Env.read_env()

BASE_DIR = Path(__file__).resolve().parent.parent


SECRET_KEY = env('SECRET_KEY')

DEBUG = False

ALLOWED_HOSTS = [env('ALLOWED_HOSTS')]

# Application definition

INSTALLED_APPS = [
    'whitenoise.runserver_nostatic',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'webpack_loader',
    'rest_framework',
    'jwt_auth',
    'etc etc',
]

MIDDLEWARE = [

    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]


STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

ROOT_URLCONF = 'project.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'client')
                 ]  
        ,
        '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',
            ],
        },
    },
]

print('templates ->', TEMPLATES)

WSGI_APPLICATION = 'project.wsgi.application'


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': env('DBNAME'),
        'HOST': env('DBHOST'),
        'PORT': 5432, 
        'USER': env('DBUSER'),
        'PASSWORD': env('DBPASS')
    }
}



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',
    },
]


LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "client", "build", "static"),
)

print('static-files ->', STATICFILES_DIRS)

STATIC_ROOT = (
    os.path.join(BASE_DIR, "static")
)

print('static-root ->', STATIC_ROOT)


DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

AUTH_USER_MODEL = 'jwt_auth.User'

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'jwt_auth.authentication.JWTAuthentication',
    ),
}


WEBPACK_LOADER = {
    'DEFAULT': {
        'CACHE': not DEBUG,
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
        'POLL_INTERVAL': 0.1,
        'IGNORE': [r'.+\.hot-update.js', r'.+\.map'],
    }
}

Hm, here's a similar repository, the result of the cookiecutter-django project, that I successfully deployed to Azure: https://github.com/pamelafox/cookiecutter-django-output/

Here's the settings file: https://github.com/pamelafox/cookiecutter-django-output/blob/main/config/settings/base.py

It doesn't use os.path.join() and instead uses the "/" as a join operator. For example:

APPS_DIR = ROOT_DIR / "my_awesome_project"

From my reading of the os.path.join() docs, its not clear to me that it should work with a Path() object. It's interesting that it works locally but not on production, but perhaps you're using a different Python version locally than on production?

Perhaps you could try "/" path formation instead.

Here's a post I wrote recently with general tips for debugging Django apps on Azure App Service:

http://blog.pamelafox.org/2023/01/tips-for-debugging-django-app.html

Solved for anyone with a similar error:

Replaced this:

STATIC_ROOT = ( os.path.join(BASE_DIR, "static") )

With:

STATIC_ROOT = ( BASE_DIR.as_posix() + '/static' )

As per Pamela's response, os.path.join does not appear to be supported in production or on some Python versions.

Back to Top