I am trying to deploy a sample application on AWS. My folder structure:
eb_django_app
├── .ebextensions
│ └── 01-django_eb.config
├── .elasticbeanstalk
│ └── config.yml
├── predictfare
│ ├── .gitignore
│ ├── db.sqlite3
│ ├── manage.py
│ ├── predictfare
│ │ ├── __init__.py
│ │ ├── __init__.pyc
│ │ ├── settings.py
│ │ ├── settings.pyc
│ │ ├── urls.py
│ │ ├── urls.pyc
│ │ ├── wsgi.py
│ │ └── wsgi.pyc
│ │
│ └── templates
│ └── base.html
└── requirements.txt
My 01-django_eb.config:
option_settings:
"aws:elasticbeanstalk:application:environment":
DJANGO_SETTINGS_MODULE: "predictfare.settings"
PYTHONPATH: "/opt/python/current/app/predictfare:$PYTHONPATH"
"aws:elasticbeanstalk:container:python":
WSGIPath: "predictfare/predictfare/wsgi.py"
My config.yml:
branch-defaults:
default:
environment: faremagus-dev
group_suffix: null
global:
application_name: faremagus
default_ec2_keyname: aws-eb
default_platform: Python 2.7
default_region: us-west-2
profile: eb-cli
sc: null
Logs Show : Target WSGI script not found or unable to stat: /opt/python/current/app/predictfare/predictfare
Mostly followed this tutorial. When I run eb open I see 404 in the browser. What am I missing?
Related
My project folder looks this:
├── Procfile
├── core
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-39.pyc
│ │ └── views.cpython-39.pyc
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── db.sqlite3
├── inspirationSources.txt
├── manage.py
├── package-lock.json
├── package.json
├── react-frontend
│ ├── README.md
│ ├── build
│ │ ├── asset-manifest.json
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ ├── robots.txt
│ │ └── static
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ └── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── assets
│ ├── components
│ ├── hooks
│ ├── index.css
│ └── index.js
├── requirements.txt
├── spotify
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-39.pyc
│ │ ├── admin.cpython-39.pyc
│ │ ├── apps.cpython-39.pyc
│ │ ├── cluster.cpython-39.pyc
│ │ ├── credentials.cpython-39.pyc
│ │ ├── models.cpython-39.pyc
│ │ ├── urls.cpython-39.pyc
│ │ ├── util.cpython-39.pyc
│ │ └── views.cpython-39.pyc
│ ├── admin.py
│ ├── apps.py
│ ├── cluster.py
│ ├── credentials.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── __init__.py
│ │ └── __pycache__
│ ├── models.py
│ ├── templates
│ ├── tests.py
│ ├── urls.py
│ ├── util.py
│ └── views.py
├── spotifycluster
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-39.pyc
│ │ ├── settings.cpython-39.pyc
│ │ ├── urls.cpython-39.pyc
│ │ └── wsgi.cpython-39.pyc
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── tutorialSources.txt
When I deploy with git push heroku main it seems to be fine but when I open the app in browser using the complementary url, I get the following errors on screen (debug mode is on):
TemplateDoesNotExist at /
build/index.html
Request Method: GET
Request URL: https://nameless-taiga-02413.herokuapp.com/
Django Version: 3.1.7
Exception Type: TemplateDoesNotExist
Exception Value:
build/index.html
Exception Location: /app/.heroku/python/lib/python3.9/site-packages/django/template/loader.py, line 19, in get_template
Python Executable: /app/.heroku/python/bin/python
Python Version: 3.9.4
Python Path:
['/app/.heroku/python/bin',
'/app',
'/app/.heroku/python/lib/python39.zip',
'/app/.heroku/python/lib/python3.9',
'/app/.heroku/python/lib/python3.9/lib-dynload',
'/app/.heroku/python/lib/python3.9/site-packages']
Server time: Fri, 30 Apr 2021 10:08:26 +0000
Template-loader postmortem
Django tried loading these templates, in this order:
Using engine django:
django.template.loaders.filesystem.Loader: /app/react-frontend/build/index.html (Source does not exist)
django.template.loaders.app_directories.Loader: /app/.heroku/python/lib/python3.9/site-packages/django/contrib/admin/templates/build/index.html (Source does not exist)
django.template.loaders.app_directories.Loader: /app/.heroku/python/lib/python3.9/site-packages/django/contrib/auth/templates/build/index.html (Source does not exist)
I have the following settings in my settings.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
Also I have whitenoise in my middleware list
MIDDLEWARE = [
'whitenoise.middleware.WhiteNoiseMiddleware',
...]
The templates section in settings.py looks as follows
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'react-frontend')],
'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',
],
},
},
]
I expected that Heroku would be able to find the static folder based on the STATIC_DIRS variable but that doesn't seem to be the case. Any clue what's going on here?
So actually it was a really stupid mistake. react-frontend was a broken submodule and I needed to fix that by making sure .git/config didn't have submodules and removing react-frontend from the cache (No submodule mapping found in .gitmodules for path and missing .gitmodules file). Commit and pushed again and it worked...
if your DEBUG is set to False Django din't handle STATIC FILES. Heroku provide some configuration to serve STATIC FILES
STEP-1 : install whitenoise
$ pip install whitenoise
STEP-2 : check in settings.py whitenoise middleware by default it available in MIDDLEWARE if it's not that add it.
MIDDLEWARE = (
'whitenoise.middleware.WhiteNoiseMiddleware',
...)
STEP-3: add this in your settings.py
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
My Django project uses Docker, gunicorn, and whitenoise. I recently altered settings to prepare for deployment, most notably adding configurations for AWS-hosted media files. Now when I run the project locally and collectstatic the static files do not update in the browser. I do, however, see the changes where static files are collected.
Things I've tried/double checked:
Ensuring I have a shared volume between the container and where static files are kept/updated
Adding a step to collectstatic in my Dockerfile
Confirming my static files settings
Is something about django-storages causing the issue? I thought that previously I was able to make SCSS changes and have them show up by refreshing the browser. But that's not happening. Even running collectstatic inside the container has no effect.
# relevant settings.py
INSTALLED_APPS = [
...
"whitenoise.runserver_nostatic",
"storages",
...
]
MIDDLEWARE = [
"django.middleware.cache.UpdateCacheMiddleware",
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
...
]
# AWS config (use in production only)
USE_S3 = env.bool("USE_S3", default=not DEBUG)
if USE_S3:
AWS_ACCESS_KEY_ID = env.str("AWS_ACCESS_KEY_ID", default="")
AWS_SECRET_ACCESS_KEY = env.str("AWS_SECRET_ACCESS_KEY", default="")
AWS_STORAGE_BUCKET_NAME = env.str("AWS_STORAGE_BUCKET_NAME", default="")
AWS_DEFAULT_ACL = None
AWS_S3_REGION_NAME = env.str("AWS_S3_REGION_NAME", default="us-east-2")
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
# S3 Public Media Settings
PUBLIC_MEDIA_LOCATION = 'media'
MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{PUBLIC_MEDIA_LOCATION}/'
# S3 Private Media Settings
DEFAULT_FILE_STORAGE = 'config.storage_backends.PrivateMediaStorage'
PRIVATE_MEDIA_LOCATION = 'private'
PRIVATE_FILE_STORAGE = 'config.storage_backends.PrivateMediaStorage'
else:
MEDIA_URL = "/media/"
MEDIA_ROOT = str(BASE_DIR.joinpath("media"))
STATIC_ROOT = str(BASE_DIR.joinpath("staticfiles"))
STATIC_URL = '/static/'
STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'
DEBUG_PROPAGATE_EXCEPTIONS = True
STATICFILES_FINDERS = (
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
"pipeline.finders.PipelineFinder",
)
PIPELINE_YUGLIFY_BINARY = "/usr/local/bin/node"
PIPELINE = {
"CSS_COMPRESSOR": "pipeline.compressors.yuglify.YuglifyCompressor",
"COMPILERS": (
"pipeline.compilers.sass.SASSCompiler",
"config.compilers.RollupCompiler",
),
"YUGLIFY_BINARY": str(BASE_DIR.joinpath("node_modules/.bin", "yuglify")),
"SASS_BINARY": str(BASE_DIR.joinpath("node_modules/.bin", "sass")),
"STYLESHEETS": {
"twirlmate": {
"source_filenames": ("pages/scss/styles.scss",),
"output_filename": "css/styles.css",
}
},
"JS_COMPRESSOR": "pipeline.compressors.NoopCompressor", # TODO: Update this to jsmin or something better.
"ROLLUP_BINARY": str(BASE_DIR.joinpath("node_modules/.bin", "rollup")),
"ROLLUP_ARGUMENTS": ["--config", "--configDebug", "--format", "iife"],
"DISABLE_WRAPPER": True,
"JAVASCRIPT": {
"twirlmate": {
"source_filenames": (
"pages/js/core.js",
"pages/js/file-field.js",
"pages/js/lazy-loading.js",
"pages/js/modal.js",
"pages/js/navigation.js",
"pages/js/notifications.js",
),
"output_filename": "js/twirlmate.js",
},
"components": {
"source_filenames": ("pages/js/vue/components.rollup.js",),
"output_filename": "js/components.js",
},
},
}
#docker-compose.yml
version: '3.8'
services:
web:
build: .
command: gunicorn config.wsgi -b 0.0.0.0:8000
volumes:
- .:/code
ports:
- 8000:8000
depends_on:
- db
environment:
- "DJANGO_SECRET_KEY=****"
- "DJANGO_DEBUG=True"
- "DJANGO_SECURE_SSL_REDIRECT=False"
- "SECURE_HSTS_SECONDS=0"
- "SECURE_HSTS_INCLUDE_SUBDOMAINS=False"
- "SECURE_HSTS_PRELOAD=False"
- "SESSION_COOKIE_SECURE=False"
- "CSRF_COOKIE_SECURE=False"
db:
image: postgres:11
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- "POSTGRES_HOST_AUTH_METHOD=trust"
volumes:
postgres_data:
# Dockerfile
# Pull base image
FROM python:3.8
# Set environment variables and build arguments
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt-get install -y nodejs build-essential
# Set working directory
WORKDIR /code
RUN npm install sass --also=dev
RUN npm install yuglify --also=dev
RUN npm install
# Install dependencies
COPY Pipfile Pipfile.lock /code/
# Figure out conditional installation of dev dependencies
# Will need to remove --dev flag for production
RUN pip install pipenv && pipenv install --system --dev
COPY . /code/
# Collect static files
RUN python manage.py collectstatic --noinput
Project Structure
twirlmate
├── .babelrc
├── .env
├── .gitignore
├── .pylintrc
├── Dockerfile
├── Makefile
├── Pipfile
├── Pipfile.lock
├── config
│ ├── __init__.py
│ ├── asgi.py
│ ├── compilers.py
│ ├── compressors.py
│ ├── constants.py
│ ├── settings.py
│ ├── storage_backends.py
│ ├── urls.py
│ └── wsgi.py
├── docker-compose.yml
├── heroku.yml
├── manage.py
├── package-lock.json
├── package.json
├── pages
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── static
│ │ └── pages
│ │ ├── css
│ │ │ ├── styles.css
│ │ │ └── styles.css.map
│ │ ├── fonts
│ │ ├── images
│ │ ├── js
│ │ │ └── vue
│ │ │ ├── components
│ │ │ │ ├── cards
│ │ │ │ ├── inputs
│ │ │ │ ├── miniMenus
│ │ │ │ └── modals
│ │ │ ├── components.rollup.js
│ │ │ ├── data
│ │ │ ├── directives
│ │ │ ├── forms
│ │ │ ├── mixins
│ │ │ ├── services
│ │ │ ├── views
│ │ │ └── vue-store.js
│ │ └── scss
│ │ ├── 01-utilities
│ │ ├── 02-vendors
│ │ ├── 03-base
│ │ ├── 04-layout
│ │ ├── 05-components
│ │ ├── 06-pages
│ │ ├── styles.css
│ │ ├── styles.css.map
│ │ └── styles.scss
│ ├── templatetags
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ ├── css_classes.py
│ │ └── url_paths.py
│ ├── tests
│ │ ├── __init__.py
│ │ └── test_views.py
│ ├── urls.py
│ └── views.py
├── pyproject.toml
├── rollup.config.js
├── staticfiles
│ ├── admin
│ ├── debug_toolbar
│ ├── django_extensions
│ ├── pages
│ │ ├── css
│ │ │ ├── styles.css
│ │ │ └── styles.css.map
│ │ ├── fonts
│ │ ├── images
│ │ ├── js
│ │ │ └── vue
│ │ │ ├── components
│ │ │ │ ├── cards
│ │ │ │ ├── inputs
│ │ │ │ ├── miniMenus
│ │ │ │ └── modals
│ │ │ ├── components.rollup.js
│ │ │ ├── components.rollup.roll.js
│ │ │ ├── data
│ │ │ ├── directives
│ │ │ ├── forms
│ │ │ ├── mixins
│ │ │ ├── views
│ │ │ └── vue-store.js
│ │ └── scss
│ │ ├── 01-utilities
│ │ ├── 02-vendors
│ │ ├── 03-base
│ │ ├── 04-layout
│ │ ├── 05-components
│ │ ├── 06-pages
│ │ ├── styles.css
│ │ ├── styles.css.map
│ │ └── styles.scss
│ └── rest_framework
└── templates
├── 403.html
├── _base.html
├── account
│ ├── login.html
│ ├── password_change.html
│ ├── password_change_done.html
│ ├── password_reset.html
│ ├── password_reset_done.html
│ ├── password_reset_from_key.html
│ ├── password_reset_from_key_done.html
│ └── signup.html
├── emails
│ ├── duet_invitation.html
│ └── duet_invitation.txt
├── includes
│ ├── _favicons.html
│ ├── _footer.html
│ ├── _header.html
│ └── forms
│ ├── _widgets.html
│ └── attrs.html
├── index.html
├── pages
│ ├── for_coaches.html
│ ├── for_directors.html
│ └── home.html
├── registration
│ ├── account-settings.password-change-done.html
│ ├── account-settings.password-change.html
│ ├── account-settings.profile-list.html
│ └── privacy-policy.html
└── studios
├── _studio_admin_base.html
├── my_studios.html
├── staff_list.html
├── studio_create.html
├── studio_detail.admin.html
├── studio_detail.html
├── studio_join.html
├── studio_list.html
├── studio_update.html
└── team_list.html
index.html, from which all other templates inherit
{% load static pipeline %}
<!doctype html>
<html class="no-js" lang="en">
<head>
... other various meta tags ...
{% stylesheet 'twirlmate' %}
<!-- the above produces the path: /static/pages/scss/styles.css -->
{% block styles %}{% endblock %}
{% block extrastyles %}{% endblock %}
</head>
<body class="{% block body-class %}{% endblock %}" {% block body-attributes %}{% endblock %}>
<div class="main-wrapper" data-target="main-wrapper">
<a class="skip-to-main" href="#main">Skip to main content</a>
{% block header %}{% endblock header %}
{% block notifications %}{% endblock notifications %}
{% block main %}{% endblock main %}
{% block footer %}{% endblock footer %}
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
{% javascript 'twirlmate' %}
{% javascript 'components' %}
{% block scripts %}{% endblock scripts %}
{% block extrascripts %}{% endblock extrascripts %}
</body>
</html>
SOLVED
It turns out there was a duplicate, stale file with the same name, and the same path. The template was looking for /static/pages/scss/styles.css, which existed in its updated form in my root static directory, the correct spot. But there was also a file in pages/static/pages/scss/styles.css that must've gotten generated during previous changes to settings.py. Somehow I guess that file was getting repeatedly pulled in and overwriting the updated version. All was fixed once I deleted the stale file.
i'm having some trouble figuring out how to manage my scss files. Here's what my folder structure looks like:
manage.py
├── myWebsite
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── projects
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── static
│ │ └── projects
│ │ └── css
│ │ ├── index.css
│ │ ├── scss
│ │ │ └── survey.scss
│ │ └── tribute.css
│ ├── templates
│ │ └── projects
│ │ ├── base.html
│ │ ├── documentation.html
│ │ ├── index.html
│ │ ├── portfolio.html
│ │ ├── product.html
│ │ ├── survey.html
│ │ └── tribute.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── requirements.txt
└── staticfiles
└── projects
└── css
└── scss
├── survey.css
└── survey.css.map
I'd like to keep my .scss files inside the static/{app_name}/css/scss folder of each app. Those are later compiled inside the staticfiles folder which is in the project root. That same folder is the root for collectstatic, which is run when deploying on the server (AWS EB)
02_collectstatic:
command: "source /opt/python/run/venv/bin/activate && python manage.py collectstatic --noinput"
Since I'm using Django 2.2 it should be possible to ignore .scss files to be collected by collectstatic but doesn't seem to be working, I tried:
python manage.py collectstatic --noinput -i projects/static/projects/css/scss
EDIT: this is the kind of error I get:
Activity execution failed, because: usage: manage.py collectstatic [-h] [--noinput] [--no-post-process]
[-i PATTERN] [-n] [-c] [-l]
[--no-default-ignore] [--version]
[-v {0,1,2,3}] [--settings SETTINGS]
[--pythonpath PYTHONPATH] [--traceback]
[--no-color] [--force-color]
manage.py collectstatic: error: unrecognized arguments: /projects/static/projects/css/scss
(ElasticBeanstalk::ExternalInvocationError)
I think you are pointing to the wrong path when you are using -i. You need to find the path from static directory root, not project root. For example if your static directory is:
STATICFILES_DIRS = [
os.path.join(APPS_DIR, "static"), # where projects is the apps directory
]
# OR if you are using django-cookie-cutter
# STATICFILES_DIRS = [str(APPS_DIR.path("static"))]
Then, update the code like this:
python manage.py collectstatic --noinput -i projects/css/scss
Following Django 2.2 Release Notes,
Added path matching to the collectstatic --ignore option so that patterns like /vendor/*.js can be used.
python manage.py collectstatic --noinput --ignore /projects/static/projects/css/scss
I developed locally using Docker and cookiecutter-django.
Cookiecutter-django creates several Dockerfiles within the "compose" directory.
I am now trying to push the project to Heroku.
However, heroku container:push web will return No images to push.
If I try the same command within a subdirectory of the compose directory, it will eventually break--probably due to an attempt at only pushing partial dockerfiles.
How do I get this up and running on Heroku taking advantage of Heroku containers?
This article from Heroku says I can push multiple images using by renaming the Dockerfiles, but I'm not sure how to figure out which of these cookiecutter-generated Dockerfiles are of which process type.
docker images will return:
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 16e570f295a7 10 minutes ago 318MB
luup_celeryworker latest bd7ff7e5eb10 2 hours ago 531MB
luup_django latest bd7ff7e5eb10 2 hours ago 531MB
luup_celerybeat latest bd7ff7e5eb10 2 hours ago 531MB
luup_postgres latest e50eb7b8a704 2 hours ago 287MB
registry.heroku.com/fierce-forest-57627/web latest 27690b3e49d4 16 hours ago 766MB
python 3.6-alpine c3a4a35c9244 22 hours ago 90MB
This is the Dockerfile made by cookiecutter. It is the DF under compose/production/django. There are other DFs--for caddy, postgres, as well as DFs for local.
FROM python:3.6-alpine
ENV PYTHONUNBUFFERED 1
RUN apk update \
# psycopg2 dependencies
&& apk add --virtual build-deps gcc python3-dev musl-dev \
&& apk add postgresql-dev \
# Pillow dependencies
&& apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev \
# CFFI dependencies
&& apk add libffi-dev openssl-dev py-cffi
RUN addgroup -S django \
&& adduser -S -G django django
# Requirements have to be pulled and installed here, otherwise caching won't work
COPY ./requirements /requirements
RUN pip install --no-cache-dir -r /requirements/production.txt \
&& rm -rf /requirements
COPY ./compose/production/django/gunicorn.sh /gunicorn.sh
RUN sed -i 's/\r//' /gunicorn.sh
RUN chmod +x /gunicorn.sh
RUN chown django /gunicorn.sh
COPY ./compose/production/django/entrypoint.sh /entrypoint.sh
RUN sed -i 's/\r//' /entrypoint.sh
RUN chmod +x /entrypoint.sh
RUN chown django /entrypoint.sh
COPY ./compose/production/django/celery/worker/start.sh /start-celeryworker.sh
RUN sed -i 's/\r//' /start-celeryworker.sh
RUN chmod +x /start-celeryworker.sh
COPY ./compose/production/django/celery/beat/start.sh /start-celerybeat.sh
RUN sed -i 's/\r//' /start-celerybeat.sh
RUN chmod +x /start-celerybeat.sh
COPY . /app
RUN chown -R django /app
USER django
WORKDIR /app
ENTRYPOINT ["/entrypoint.sh"]
Please let me know if you need any more information
Edit--adding tree:
note: I've renamed the Dockerfiles to Dockerfile.processtype as instructed by Heroku here--Although I'm no longer pushing multiple images.. As you can tell in the tree, I've also moved a copy of Dockerfile.django and Dockerfile.local to the root of the project, as that's where it needs to be in order to Heroku container:push processtype --recursive.
├── Dockerfile.django
├── Dockerfile.local
├── LICENSE
├── Procfile
├── README.rst
├── compose
│ ├── local
│ │ └── django
│ │ ├── celery
│ │ │ ├── beat
│ │ │ │ └── start.sh
│ │ │ └── worker
│ │ │ └── start.sh
│ │ └── start.sh
│ └── production
│ ├── caddy
│ │ ├── Caddyfile
│ │ └── Dockerfile.caddy
│ ├── django
│ │ ├── Dockerfile.django
│ │ ├── celery
│ │ │ ├── beat
│ │ │ │ └── start.sh
│ │ │ └── worker
│ │ │ └── start.sh
│ │ ├── entrypoint.sh
│ │ └── gunicorn.sh
│ └── postgres
│ ├── Dockerfile.postgres
│ └── maintenance
│ ├── _sourced
│ │ ├── constants.sh
│ │ ├── countdown.sh
│ │ ├── messages.sh
│ │ └── yes_no.sh
│ ├── backup
│ ├── backups
│ └── restore
├── config
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── __init__.cpython-36.pyc
│ │ ├── urls.cpython-36.pyc
│ │ └── wsgi.cpython-36.pyc
│ ├── settings
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-35.pyc
│ │ │ ├── __init__.cpython-36.pyc
│ │ │ ├── base.cpython-35.pyc
│ │ │ ├── base.cpython-36.pyc
│ │ │ ├── local.cpython-35.pyc
│ │ │ ├── local.cpython-36.pyc
│ │ │ └── production.cpython-36.pyc
│ │ ├── base.py
│ │ ├── local.py
│ │ ├── production.py
│ │ └── test.py
│ ├── urls.py
│ └── wsgi.py
├── docs
│ ├── Makefile
│ ├── __init__.py
│ ├── conf.py
│ ├── deploy.rst
│ ├── docker_ec2.rst
│ ├── index.rst
│ ├── install.rst
│ └── make.bat
├── heroku.yml
├── local.yml
├── locale
│ └── README.rst
├── lurnup
│ ├── __init__.py
│ ├── __pycache__
│ │ └── __init__.cpython-36.pyc
│ ├── contrib
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ └── __init__.cpython-36.pyc
│ │ └── sites
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ └── __init__.cpython-36.pyc
│ │ └── migrations
│ │ ├── 0001_initial.py
│ │ ├── 0002_alter_domain_unique.py
│ │ ├── 0003_set_site_domain_and_name.py
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ ├── 0001_initial.cpython-36.pyc
│ │ ├── 0002_alter_domain_unique.cpython-36.pyc
│ │ ├── 0003_set_site_domain_and_name.cpython-36.pyc
│ │ └── __init__.cpython-36.pyc
│ ├── static
│ │ ├── css
│ │ │ └── project.css
│ │ ├── fonts
│ │ ├── images
│ │ │ └── favicon.ico
│ │ ├── js
│ │ │ └── project.js
│ │ └── sass
│ │ ├── custom_bootstrap_vars.scss
│ │ └── project.scss
│ ├── taskapp
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-36.pyc
│ │ │ └── celery.cpython-36.pyc
│ │ └── celery.py
│ ├── templates
│ │ ├── 403_csrf.html
│ │ ├── 404.html
│ │ ├── 500.html
│ │ ├── account
│ │ │ ├── account_inactive.html
│ │ │ ├── base.html
│ │ │ ├── email.html
│ │ │ ├── email_confirm.html
│ │ │ ├── login.html
│ │ │ ├── logout.html
│ │ │ ├── password_change.html
│ │ │ ├── password_reset.html
│ │ │ ├── password_reset_done.html
│ │ │ ├── password_reset_from_key.html
│ │ │ ├── password_reset_from_key_done.html
│ │ │ ├── password_set.html
│ │ │ ├── signup.html
│ │ │ ├── signup_closed.html
│ │ │ ├── verification_sent.html
│ │ │ └── verified_email_required.html
│ │ ├── base.html
│ │ ├── pages
│ │ │ ├── about.html
│ │ │ └── home.html
│ │ └── users
│ │ ├── user_detail.html
│ │ ├── user_form.html
│ │ └── user_list.html
│ └── users
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ ├── adapters.cpython-36.pyc
│ │ ├── admin.cpython-36.pyc
│ │ ├── apps.cpython-36.pyc
│ │ ├── models.cpython-36.pyc
│ │ ├── urls.cpython-36.pyc
│ │ └── views.cpython-36.pyc
│ ├── adapters.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ ├── 0001_initial.cpython-36.pyc
│ │ └── __init__.cpython-36.pyc
│ ├── models.py
│ ├── tests
│ │ ├── __init__.py
│ │ ├── factories.py
│ │ ├── test_admin.py
│ │ ├── test_models.py
│ │ ├── test_urls.py
│ │ └── test_views.py
│ ├── urls.py
│ └── views.py
├── manage.py
├── merge_production_dotenvs_in_dotenv.py
├── production.yml
├── pytest.ini
├── requirements
│ ├── base.txt
│ ├── local.txt
│ └── production.txt
Cookiecutter-django provides a standard docker compose configuration that you can push on several hosting services with full Docker support.
However, Heroku supports Docker with a few restrictions. For instance, the port for the WSGI server is hardcoded to 5000, where Heroku requires to use the environment variable $PORT.
These are NOT accounted for in cookiecutter-django, so you will have to change a few things:
I'd start with the images in compose/production/django and ignore the DB (prvided via add-on) and Caddy (see here instead).
Change the Gunicorn port from 5000 to $PORT
The code to get DATABASE_URL in entrypoint.sh should probably not be needed.
Last but not least: create a heroku.yml file to point at the DF you want to use.
With docker-compose, you can re-use the same Dockerfile and change the entrypoint, but I don't think it's feasible with Heroku. You might need to create a duplicate the web Dockerfile and change it for your Celery dynos.
I've tried Docker on Heroku, but not with cookiecutter-django' setup. The Heroku way is not standard enough IMO, it's a bit of a middle ground between pure Heroku and bare Docker.
Hope that helps!
Hi I am trying to integrate foundation scss into django using django-compressor's precompiler, the project looks like this:
├── manage.py
├── requirements.txt
├── static
│ ├── config.rb
│ ├── humans.txt
│ ├── index.html
│ ├── javascripts
│ │ ├── foundation
│ │ │ ├── foundation.alerts.js
│ │ │ ├── foundation.clearing.js
│ │ │ ├── foundation.cookie.js
│ │ │ ├── foundation.dropdown.js
│ │ │ ├── foundation.forms.js
│ │ │ ├── foundation.joyride.js
│ │ │ ├── foundation.js
│ │ │ ├── foundation.magellan.js
│ │ │ ├── foundation.orbit.js
│ │ │ ├── foundation.placeholder.js
│ │ │ ├── foundation.reveal.js
│ │ │ ├── foundation.section.js
│ │ │ ├── foundation.tooltips.js
│ │ │ └── foundation.topbar.js
│ │ └── vendor
│ │ ├── custom.modernizr.js
│ │ ├── jquery.js
│ │ └── zepto.js
│ ├── MIT-LICENSE.txt
│ ├── robots.txt
│ ├── sass
│ │ ├── app.scss
│ │ ├── normalize.scss
│ │ └── _settings.scss
│ └── stylesheets
│ ├── app.css
│ └── normalize.css
├── templates
│ ├── 404.html
│ ├── 500.html
│ ├── admin
│ │ └── base_site.html
│ └── base.html
└── weddings
├── __init__.py
├── __init__.pyc
├── local_settings.py
├── local_settings.pyc
├── settings.py
├── settings.pyc
├── urls.py
├── urls.pyc
└── wsgi.py
and the precompiler looks like this in settings.py
COMPRESS_PRECOMPILERS = (
('text/x-scss', 'sass --scss --compass {infile} {outfile}'),
)
And when I run it with nginx + uwsgi, I get the following error:
Syntax error: File to import not found or unreadable: foundation/foundation-global.
Load paths:
/etc/uwsgi/vassals
/etc/uwsgi/vassals/sass
/srv/www/weddings/gems/compass-0.12.2/frameworks/blueprint/stylesheets
/srv/www/weddings/gems/compass-0.12.2/frameworks/compass/stylesheets
Compass::SpriteImporter
/srv/www/weddings/gems/bourbon-3.1.1/app/assets/stylesheets
/srv/www/weddings/gems/bourbon-3.1.1/app/assets/stylesheets
on line 2 of /srv/www/weddings/weddings/static/sass/_settings.scss
from line 2 of /srv/www/weddings/weddings/static/sass/app.scss
Use --trace for backtrace.
I suspect it's not reading the config.rb or the settings in config.rb is wrong:
http_path = "/"
css_dir = "stylesheets"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "javascripts"
As you have a config.rb file, you have a Compass project.
Compass projects are supposed to be compiled with the compass command line tool, not sass command line tool.
As you have already discovered, compilation should be launched from insie the project folder. But it's a bad idea to hardcode the path into settings.py as it makes your project unportable.
Instead of a hardcoded path, you should use os.path.dirname(os.path.realpath(__file__)) to discover current script's path. To change the folder relative to settings.py, use os.path.join() like this (adjust as necessary, you can use ..):
os.path.join(os.path.dirname(os.path.realpath(__file__)), "static")
Also, you may already have PROJECT_DIR var in your settings.py. Use it to make this line cleaner.
A little improvement to #James Lin
COMPRESS_PRECOMPILERS = (
# ('text/x-scss', 'django_libsass.SassCompiler'),
# ('text/x-scss', 'sass --scss {infile} {outfile}'),
('text/x-scss', 'sass --scss --compass {infile} {outfile}'),
)
My current work around is to run the sass command in the folder where ocnfig.rb is located
COMPRESS_PRECOMPILERS = (
('text/x-scss', 'cd /srv/www/project/name/static && sass --scss --compass {infile} {outfile}'),
)