3👍
I didn’t find the answer to this in all my searching, so here it is:
- This is only properly implemented in Django 3.1.6, so 1.8 won’t work.
proxy_pass http://127.0.0.1:8000/
is wrong, you needproxy_pass http://127.0.0.1:8000
(without the trailing backslash) in order to keep/myapp
at the start of the URL path. Django expects its requests to start with the value of theSCRIPT_NAME
header, and strips it off before your apps see it. Django will return an error for any URL that doesn’t start like this.- If your
settings.py
definesSTATIC_URL
as an absolute path like/static/
, Django will not prepend it with your script name. Use a relative path likestatic/
. - If there are any other proxies in between, make sure they are not dropping the
STATIC_FILES
header. For example, if you have another nginx in between then you need to make sure that yourserver
block contains the lineunderscores_in_headers on;
. - settings like
LOGIN_REDIRECT_URL
are not prepended (and you cannot use the relative path trick as this does something different), so you can fudge this with a line:proxy_redirect / /myapp/;
, but then most redirects are prepended, so you also need a line before that:proxy_redirect /myapp/ /myapp/;
. This technique will not work if/myapp/myapp
is actually a valid path, of course. - If you want to serve the static files statically, remember to include a location block for that.
So your nginx block should look a bit like this:
location /myapp/ {
proxy_pass http://127.0.0.1:8000;
proxy_set_header SCRIPT_NAME /myapp;
proxy_redirect /myapp/ /myapp/;
proxy_redirect / /myapp/;
location /myapp/static/ {
root /var/www; # files are deployed to /var/www/myapp/static
}
}
and in settings.py
:
STATIC_URL=`static/`
and in requirements.txt
:
Django==3.1.6
What a nightmare. Does anybody have any better ideas?
2👍
I was able to partially resolve this with some help from the following snippet: http://flask.pocoo.org/snippets/35/
location /myapp {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Script-Name /myapp;
}
Then I created a wsgi.py
file in the myapp folder with:
from django.core.wsgi import get_wsgi_application
_application = get_wsgi_application()
def application(environ, start_response):
script_name = environ.get('HTTP_X_SCRIPT_NAME', '')
if script_name:
environ['SCRIPT_NAME'] = script_name
path_info = environ['PATH_INFO']
if path_info.startswith(script_name):
environ['PATH_INFO'] = path_info[len(script_name):]
scheme = environ.get('HTTP_X_SCHEME', '')
if scheme:
environ['wsgi.url_scheme'] = scheme
return _application(environ, start_response)
I also had to switch from using
python manage.py runserver 0.0.0.0:8000
for serving the application to using uWSGI
. For this I followed the instructions at Setting up Django and your web server with uWSGI and nginx
but essentially boiled down to
pip install uwsgi
and then serving the Django app with
uwsgi --http :8000 --module myapp.wsgi
EDIT: This currently doesn’t work for static
and media
assets. See this open ticket: https://code.djangoproject.com/ticket/25598
- [Django]-Archiving Django models
- [Django]-Rest Framework Image Validation
- [Django]-Why "no such table: django_session" when trying to use admin?
- [Django]-Authentication failed: [Errno 1] _ssl.c:510: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
- [Django]-Proper implementation of Django model inheritance architecture?
0👍
Well that was another one day journey in trying to get things work. Now with success and not to much efforts. Here is a working example off getting django 3.2 run behind traefik on a subpath and on another port:
docker-compose.yaml
app:
build: YOUR DJANGO APP
command: gunicorn --bind=0.0.0.0 --log-level=debug --timeout 1000 --workers 1 --threads 4 herre.wsgi
ports:
- 8000:8000
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.appheaders.headers.customrequestheaders.SCRIPT_NAME=/$APP_SUB_PATH"
- "traefik.http.routers.app.rule=PathPrefix(`/$APP_SUB_PATH`)"
- "traefik.http.routers.app.middlewares=appheaders"
- "traefik.http.routers.app.entrypoints=web"
traefik:
image: "traefik:v2.5"
container_name: "traefik"
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
settings.py
STATIC_URL = "static"
LOGIN_URL = "auth_login" # <-- we can specify view names here that can be resolved by resolve_url
LOGIN_REDIRECT_URI = "index" <-- again view name
In this configuration there is no need to change the wsgi application. But beware that this does not run with "python manage.py runserver" but only with
a deployment server.
Hope that saves anyone the trouble it cost me !