Django collectstatic not working on production with S3, but same settings work locally

Ok, let me try, as discovered in comments from the question, you do S3 update using collectstatic, but this is a management command which is called using manage.py file where you set cobev.settings.local as settings which are not equal to cobev.settings.production which is used for wsgi.py file.

I think you should manage your settings file using, normal Django way, OS environment variable named DJANGO_SETTINGS_MODULE.

For sure you should be able to set it in any production environment you are running.


Then if that can help here is my config for AWS/Django/S3 in production :

Common Static config :

# STATIC FILE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root
STATIC_ROOT = str(ROOT_DIR('staticfiles'))

# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
STATIC_URL = '/static/'

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
STATICFILES_DIRS = [
    str(APPS_DIR.path('static'))
]

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder'
]

Common Media config :

# MEDIA CONFIGURATION
# ------------------------------------------------------------------------------

# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root
MEDIA_ROOT = str(APPS_DIR('media'))

# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url
MEDIA_URL = '/media/'

Production Static config :

# STATIC CONFIG PRODUCTION
# ------------------------------------------------------------------------------
# See: http://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html

AWS_STORAGE_BUCKET_NAME = 'mybucket-name-production'
AWS_ACCESS_KEY_ID = 'YOUR_KEY_ID'
AWS_SECRET_ACCESS_KEY = 'YOUR_SECRET_KEY'
AWS_S3_HOST = "s3.amazonaws.com"
AWS_S3_URL = 'https://{bucker_name}.s3.amazonaws.com/'.format(bucker_name=AWS_STORAGE_BUCKET_NAME)

AWS_LOCATION = 'static/'

AWS_S3_URL_PROTOCOL = 'https:'
AWS_S3_CUSTOM_DOMAIN = 'static.mydomain.com' # I use sub domaine to serve static 

STATIC_URL = '{AWS_S3_URL_PROTOCOL}//{AWS_S3_CUSTOM_DOMAIN}/{AWS_LOCATION}'.format(
    AWS_S3_URL_PROTOCOL=AWS_S3_URL_PROTOCOL,
    AWS_S3_CUSTOM_DOMAIN=AWS_S3_CUSTOM_DOMAIN,
    AWS_LOCATION=AWS_LOCATION)

AWS_QUERYSTRING_AUTH = False

AWS_IS_GZIPPED = True
AWS_EXPIREY = 60 * 60 * 24 * 14

# For s3boto
AWS_HEADERS = {
    'Cache-Control': 'max-age=%d, s-maxage=%d, must-revalidate' % (AWS_EXPIREY, AWS_EXPIREY)
}

# For s3boto3
AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=%d' % AWS_EXPIREY,
}

AWS_PRELOAD_METADATA = True
#AWS_S3_FILE_OVERWRITE = True

STATICFILES_STORAGE = 'config.storages.StaticStorage'
DEFAULT_FILE_STORAGE = 'config.storages.DefaultStorage'



# MEDIA S3 CONFIG PRODUCTION
# --------------------------------------------------------------------------------

AWS_MEDIA_DIR = 'media'
MEDIA_URL = AWS_S3_URL + AWS_MEDIA_DIR + '/'
MEDIA_ROOT = MEDIA_URL

Here is my StaticStorage Class :

from storages.backends.s3boto3 import S3Boto3Storage


class StaticStorage(S3Boto3Storage):
    location = 'static'
    file_overwrite = False


class DefaultStorage(S3Boto3Storage):
    location = ''
    file_overwrite = False

After That I add command in the folder .ebextensions in .config file for collectstatic :

# ./ebextensions/02_container_commands.config file : 

container_commands:
  0.3.0.push.static.to.s3:
    command: "source /opt/python/run/venv/bin/activate && python manage.py collectstatic --ignore=.scss --noinput"
    leader_only: true
    ignoreErrors: true

It looks like you are using Whitenoise. Whitenoise allows django to serve its static files. It is different approach if you want to serve them from AWS.

So, you need to remove Whitenoise in order to utilize django-storages. Remove it from settings, middleware, wsgi.py, etc.

Also, you can remove everything from __init__.py in settings - settings file to be used is set by DJANGO_SETTINGS_MODULE env variable.


According to your STATICFILES_DIRS, media directory is included as static files. It is preferred for media to be served separately from static files (one of differences - static files are more likely to be cached and gziped) - i.e. also with AWS but from separate S3 bucket.

You may also add AWS CloudFront as CDN in front of your buckets later.