Using Django 1.11.6, python 3.6.2
Short summary: static files are collected correctly on server but only one app's sub directory is served, the admin's static files return as 404.
Running the local development server everything works as expected. After deploying to my EB instance none of the static files for the admin app load. If i run eb ssh and look around on the server I can see the collected static folder, along with all the different app's subfolders. The files are all there where I'd expect. The links produced on the django front-end map in a sensible way to these paths, it's just that anything in static/admin returns a 404, while the files in static/entities work fine.
Testing paths on the front end:
/static/admin/css/base.css (404)
/static/entities/style.css (works)
On server, all collected files in static look fine:
/opt/python/current/app/static/admin/css
/opt/python/current/app/static/entities
No idea why one sub directory is server fine but the others return 404s.
From my django.config
option_settings:
"aws:elasticbeanstalk:application:environment":
DJANGO_SETTINGS_MODULE: "spf.settings"
"PYTHONPATH": "/opt/python/current/app:$PYTHONPATH"
"ALLOWED_HOSTS": ".elasticbeanstalk.com"
"aws:elasticbeanstalk:container:python":
WSGIPath: spf/wsgi.py
NumProcesses: 3
NumThreads: 20
"aws:elasticbeanstalk:container:python:staticfiles":
"/static/": "static/"
...
03_collectstatic:
command: "source /opt/python/run/venv/bin/activate && python manage.py collectstatic --noinput"
Running the collectstatic command locally produces the correct static folder with the same subdirectories for each app too.
Sheepish self-answer here:
In the AWS configuration for my eb instance I had set some static file aliases to serve directly from one of my sub apps. (Look under configuration->Software Configuration->Static Files). These aliases override any wsgi settings you may have in your django application. :)
Related
Deploying a Django app to Beanstalk this week for the first time and I successfully deployed the app, however some of the static files are returning a 403 forbidden error. I'm using Django Rest Framework which is installed as dependency. Most of the static files that are 403-ing are from the Django Rest package.
here is what i am seeing in the log
[Wed Mar 16 18:37:03.034730 2016] [authz_core:error] [pid 8842] [client 172.31.40.112:57965] AH01630: client denied by server configuration: /static, referer: {APPURL}.elasticbeanstalk.com/
my static properties in settings.py:
STATIC_URL = '/static/'
django.config
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: hungryapp/wsgi.py
aws:elasticbeanstalk:container:python:staticfiles:
/static/: /static/
In django, you can group all the static files from different directories, which you specify in the STATICFILES_DIRS variable.
There is a command called python manage.py collectstatic, that does the above job of copying all the static files in STATICFILES_DIRS, and also the static files related to the admin panel, and in this case, your Rest Framework related static files. All the static files are copied to a directory which you would have mentioned as STATIC_ROOT in your django settings file.
Now 2 things have to be made sure by you:
1) You run the python manage.py collectstatic command
2) Do a chmod -R 777 /path/to/static_root
You get 403 because the web server cannot access your static file, since it is denied the permission to read the file. Doing a chmod 777 gives the permission to read (and write and execute ) the static file, which should clear your problem.
When deploying a Django app using dokku I am getting a following error
Collectstatic configuration error. To debug, run:
$ heroku run python ./manage.py collectstatic --noinput
I found no way to run heroku run python ./manage.py collectstatic --noinput for a dokku container, but when I am trying dokku run my app python ./manage.py collectstatic --noinput, the static files are successfully copied to the STATIC_ROOT folder and no error message given.
I could solve the problem by placing collectstatic command into Procfile:
web: python manage.py collectstatic --noinput ; gunicorn myapp.wsgi
Still, I would love to know what was causing the problem and how can it be debugged. Any ideas?
You should have four settings in your settings.py file called MEDIA_ROOT, MEDIA_URL, STATIC_ROOT and STATIC_URL.
I set mine like so:
MEDIA_ROOT = 'media'
STATIC_ROOT = 'static'
MEDIA_URL = '/media'
STATIC_URL = '/static'
Inside the docker container that gets created, you will find your application under /app which makes the media path /app/media/ and the static path /app/static/.
Unfortunately if you don't have a media and static folder committed in git, it won't get created under /app automatically.
Since git doesn't allow you to commit an empty folder (it only commits files), I do the following in my projects:
mkdir media static
touch media/.dir
touch static/.dir
git add media/.dir static/.dir
git commit -m 'Make media and static directories'
The 'touch' command creates an empty file, then you 'git add' the two newly-created files and check them in.
Now when you push, the directories will be there to contain the media and static files. Just keep in mind that every time you 'git push', a new container is created, and the old one is destroyed. While this isn't a problem for your static files, your media will be lost unless you store it somewhere else.
After successfully deploying a test app using the steps outlined here:
http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_Python_flask.html
I tried to deploy my actual flask application which has the following structure:
myApp/
runServer.py
requirements.txt
myApp/
__init__.py
helpers.py
clean.sh
static/
myApp.css
handlers/
__init__.py
views.py
templates/
layout.html
viewOne.html
viewTwo.html
Where views.py contains my url mappings.
I have tried initializing the eb instance in the root directory as well as within the myApp module and git aws.push but I get the following error on the AWS dashboard:
ERROR Your WSGIPath refers to a file that does not exist. and the application does not work (404 for any path).
How can I deploy the above Flask application to elastic beanstalk?
I encountered a similar problem deploying a Flask application to EB, with a similar directory structure, and had to do 2 things:
Update my manage.py to create an object of name application, not app
import os
from application import create_app, db
from flask.ext.script import Manager, Shell
application = create_app(os.getenv('FLASK_CONFIG') or 'default')
manager = Manager(application)
Create .ebextensions/myapp.config, and define the following block to point to manage.py
option_settings:
"aws:elasticbeanstalk:container:python":
WSGIPath: manage.py
"aws:elasticbeanstalk:container:python:staticfiles":
"/static/": "application/static/"
This let Elastic Beanstalk find the application callable correctly.
This is described briefly at the official docs, and is described in more detail in this blog post
EDIT - see project structure below
ProjectRoot
.ebextensions
application.config
application
main
forms.py
views.py
static
templates
tests
manage.py
requirements.txt
config.py
etc, etc
Add the following to .ebextensions/<env-name>.config:
option_settings:
"aws:elasticbeanstalk:container:python":
WSGIPath: myApp/handlers/views.py
Update:
If you don't have .ebextensions directory, please create one for the project. You can find more information of what can be done regarding the container configuration in Customizing and Configuring AWS Elastic Beanstalk Environments guide.
Your WSGIPath refers to a file that does not exist.
This error appears because Beanstalk, by default, looks for application.py. Check at Beanstalk web UI, Configuration > Software Configuration, WSGIPath is mapped to application.py
Update the WSGIPath as shown in the previous replies or rename to application.py file.
As of awsebcli 3.0, you can actually edit your configuration settings to represent your WSGI path via eb config. The config command will then pull (and open it in your default command line text editor, i.e nano) an editable config based on your current configuration settings. You'll then search for WSGI and update it's path that way. After saving the file and exiting, your WSGI path will be updated automatically.
WSGI configuration was painful for me. I did changed WSCI settings using eb config command but it did not work. Below you can fix this in 5 easy steps.
1- Moved app.py function to the root of the directory (where I runned eb init command.
2- Also renamed app.py as application.py and in that initilized application as application = Flask(__name__) not app = Flask(__name__)
3- eb deploy did not worked after this (in the same project) I tried to fix config by using eb config but it was too hairy to sort it out. Delete all .extensions, .gitignore etc from your project.
4- re initialize your project on EB with eb init and follow the prompts. when deployment is done, eb open would launch your webapp (hopefully!)
When I encountered this problem it was because I was using the GUI to upload a zip of my project files. Initially I was zipping the project level directory and uploading that zip to EB.
Then I switched to simply uploading a zip of the project files themselves-ie select all files and send those to a zip-and then the GUI upload utility was able to find my application.py file without a problem because the application.py file was not in a subfolder.
Well, In my case I followed the entire process and conventions but was still getting 404. The problem was my virtual environment. I was ignoring all environment config related folders/files in my .gitignore but not in .ebignore. After creating .ebignore and ignoring all the folders/files which were not related to project code, fixed the issue.
I'm using AppFog PaaS system for a few days, and I love it, It's probably the best PaaS system that I've tested (I've used other 3 ones previously), but didn't find information about how to serve static content with the Web server in frontend (Apache https or nginx) I'm not sure what server is being used.
My app is a Python WSGI with CherryPy and works perfectly in AppFog but I don't wan't CherryPy to serve static content, I think that Apache httpd or nginx is a better option for that.
With Ryan's support, I'm finally able to load static files! Here are the steps:
Created a 'static' directory in the project root - here all static files will be collected running the collectstatic command.
Edit the settings.py file:
STATIC_ROOT = os.path.join( os.path.abspath( os.path.dirname(file) ), '../static' ) # May change depending on where your settings.py file is!
STATIC_URL = '/static/'
Add following line in urlpatterns variable in urls.py file:
url(r'^static/(?P.*)$', 'django.views.static.serve', { 'document_root': settings.STATIC_ROOT} ) ,
Finally, run collectstatic command in your local machine. This will copy all static files from the apps you are using:
python manage.py collectstatic
That's it. Push in AF :)
Downside: Need to run collectstatic every time we have a new static file...
Edit your nginx.conf file. In the server section enter...
# serve static files
location ~ ^/(images|javascript|css)/ {
root /var/www/html/appname;
}
images, javascript and css would be folders in your document root folder. Update all your urls accordingly.
I'm trying to deploy some Pyramid code to dotcloud. Unfortunately some paths are not mapped in the same way as in local paster deployment. When I'm running the development configuration with local server through paster serve ..., I can access static files configured in:
config.add_static_view('static', 'appname:static')
however on the dotcloud servers, when the scripts run via the following wsgi.py:
import os, sys
from paste.deploy import loadapp
current_dir = os.path.dirname(__file__)
application = loadapp('config:production.ini', relative_to=current_dir)
static content is searched for in a wrong directory. Instead of /home/dotcloud/current/static/pylons.css, it should look in /home/dotcloud/current/appname/static/pylons.css
Is there some part of wsgi configuration which can define the base directory? What am I missing? The application is run via nginx / uwsgi.
I tried to load config:../production.ini, relative_to=current_dir + '/appname' but that didn't change anything.
On DotCloud, URLs starting with /static are handled directly by nginx, not by uwsgi. That means that your code will never see those requests: they will be served straight away from the static/ subdirectory of your application.
One possible workaround is to setup a symlink from static to appname/static.
If you don't want to clutter your repository with such a symlink, you can use a postinstall script instead:
#!/bin/sh
# This creates the symlink required by DotCloud to serve static content from nginx
ln -s ~/current/appname/static ~/current/static
The symlink is sleek, but the postinstall scripts gives you the opportunity to drop in a comment in the file, to explain its purpose :-)
Future releases of DotCloud might offer a "naked configuration" toggle, where the nginx configuration won't include any special path handling, just in case you don't want them.
Meanwhile, if you want to see the nginx default configuration of your DotCloud service, you can just dotcloud ssh to your service, and inspect /etc/nginx/sites-enabled/default.