Serve static files with Nginx and custom service. Dotcloud - django

I deployed my Django app on Dotcloud.
I'm using websockets with Gevent and django-socketio, so I used a custom service. For now, I'm still using 'runserver_socketio' in order to make it works.
Now, I would like to use Nginx to serve my static files. I found this : https://github.com/dotcloud/nginx-on-dotcloud
I tried to use it. Here is my dotcloud.yml:
www:
type: custom
buildscript: nginx/builder
processes:
app: /home/dotcloud/env/bin/python myproject/manage.py runserver_socketio 0.0.0.0:$PORT_WWW
nginx: nginx
ports:
www: http
systempackages:
- libevent-dev
- python-psycopg2
- libpcre3-dev
db:
type: postgresql
And I added the folder 'nginx' at the root of my app.
I also added at the end of my postinstall:
nginx_config_template="/home/dotcloud/current/nginx/nginx.conf.in"
if [ -e "$nginx_config_template" ]; then
sed > $HOME/nginx/conf/nginx.conf < $nginx_config_template \
-e "s/#PORT_WWW#/${PORT_WWW:-42800}/g"
else
echo "($nginx_config_template) isn't there!!! Make sure it is in the correct location or else nginx won't be setup correctly."
fi
But when I go to my app, after I push it, I get the error:
403 Forbidden, nginx/1.0.14
And Nginx does serve the error pages 404.
So I don't know why, but I don't have access to my app anymore. Do you have any idea on how I can set my app with Nginx?
Thank you very much

I think Your problem is that you have two different processes fighting for the http port (80). You can only have one process running on port 80 at a time. Most people work around this by having nginx running on port 80, and then reverse proxying all traffic to the other process, which runs on a different port. This wouldn't work for you, because nginx doesn't support web sockets. So that means you would need to run nginx or the django app on a port other then 80. Which also isn't ideal.
At this point you have two other options
Use a CDN, put all of your files on Amazon S3, and serve them from there (or cloudfront).
Use dotCloud's static service, this will be a separate service that just serves the static files. Here is what your dotcloud.yml would look like.
dotcloud.yml
www:
type: custom
processes:
app: /home/dotcloud/env/bin/python myproject/manage.py runserver_socketio 0.0.0.0:$PORT_WWW
ports:
www: http
systempackages:
- libevent-dev
- python-psycopg2
- libpcre3-dev
db:
type: postgresql
static:
type: static
approot: static_media
Basically it adds a new service called static, and this new service, is looking for your static files in a directory in your project called static_media, located at the root of your project.
If you use the static service, you will need to get the URL from the static service, and set your STATIC_URL appropriately in your django settings.py.
Another gotcha with this setup, is if you are using django's static_files app. Django's static files app will copy all the static media into one common location. This doesn't work with the static service, because the static service is separate, and will most likely live on a different host then your other service, so you will need to manually copy the files into the common static_media directory your self.
For more information about the dotCloud static service, see these docs: http://docs.dotcloud.com/0.9/services/static/
Because of the gotcha I mentioned for option 2, I would recommend using option 1. Doing this is a pretty easy if you use something like https://github.com/jezdez/django_compressor . It can send your files to s3 for you.

Related

Plausible analytics on a server with a webapp

I have Django hosted with Nginx on DigitalOcean. Now I want to install Plausible Analytics. How do I do this? How do I change the Nginx config to get to the Plausible dashboard with mydomain/plausible for example?
Setup plausible by either running the software directly or in a docker container - let's say it runs on port 8080
Then in your nginx.conf - you should have a server block for your domain
Within that add a location block with the path you want plausible on and add a proxy pass directive to forward the requests to localhost:8080
Monitor access.log and error.log to debug any issues that may happen

Deploying with docker

I am new to deploying with docker. Actually, I am running my django app in my computer inside docker container, and it is running successfully on port localhost:8080. Then I pulled the code to remote server and started docker-compose up, and app is running successfully there as well. What I want to ask is that, how can I see the app with the help of ip adress of the server? For example, if the ip adress is 123.45.67.89 I think the app should be running in 123.45.67.89:8080 but it does not run there. How can I access to the app running in container in remote server?
P.S. I have not used nginx, should I use it?
docker-compose.yml
The answer to this question greatly depends on where you are hosting your production application, and what type of services it provides you out of the box.
In general, production servers usually have some reverse proxy or application load balancer sitting in front of the containerized application(s).
Since you are starting with docker, and since I am assuming this is a personal or small scale app, I can recommend the following:
If you are flexible in terms of hosting providers, try Digital Ocean. They are very developer friendly, and cost effective, at least until a certain scale point.
Use the automated docker nginx-proxy. This tool lets you add a couple of lines to your docker-compose.yml file, and magically get a configured nginx proxy, without knowing anything about nginx.
I am using this approach to deploy multiple personal websites to a single, low cost server.
An example docker-compose.yml might look like this:
services:
nginx:
image: nginxproxy/nginx-proxy
ports: ["${PORT:-80}:80"]
restart: always
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
DEFAULT_HOST: www.yoursite.com
app:
depends_on: [nginx]
restart: always
image: your/image
environment:
VIRTUAL_HOST: myapp.localhost,www.yoursite.com
which basically tells the nginx-proxy to serve your app on both http://myapp.localhost and http://www.yoursite.com.
Of course, you will need to point your domains DNS to your digital ocean IP.
Technically, it should work the way you did it, but maybe the port 8080 is not open to the outside world.
You could change the port mapping in your docker-compose.yml file:
ports:
- "80":"8080"
You can then access your app from 123.45.67.89, without any port specified since 80 is the default. If it doesn't work, double check the ip address and your firewall rules.
However, using Nginx is almost always a good idea since the local web server you are using is not production ready (feature and security wise). I'll not explain how to implement Nginx here because it's a little bit off topic and there is a lot of resource available, but you should seriously consider it when you are deploying on a remote server.

How to serve Flask app on different port than main site running on port 80?

Read through the other threads, but none seemed to address my need.
I have a website running fine on default port 80/443 using Apache on CentOS 7.
I have now installed gunicorn and copied my files to a /api subdirectory on the server. I am able to start gunicorn successfully using "gunicorn -b 0.0.0.0:8000 api:app"; however, I don't seem to be able to browse to https://example.com:8000 (site can't be reached).
Do I need to use a VirtualHost's file specifically for the Flask /api directory? If so, what would that look like without disrupting the main site?
EDIT: Note this is a Flask-RESTful API, no static files or anything on the Flask side. Just endpoints/routes to serve.

Does Caddy server serves Django static and media files?

No. 4 of this says
Take care of your statics and medias
Normally I takes care them by Nginx in dev-server or S3/CloudFront in prod-server. But this time I judge Caddy is a webserver like Nginx. Then I read on the DockerFile. But I couldn't find any example of them
Question:
My understanding is when I use Caddy I have to use something else to serve statics and medias.
Am I correct?
If not please show the reference then I will study further
According to caddy website it is able to serve static files. You can tell Caddy to serve static files by using except keyword:
domain.tld {
root /var/www/project/folder
proxy / localhost:8000 {
transparent
except /static
}
}
Assuming that your static files are stored under /var/www/project/folder/static, any url that begins with domain.tld/static/ should be served by Caddy server as static file.

What is the purpose of NGINX and Gunicorn running in parallel?

A lot of Django app deployments over Amazon's EC2 use HTTP servers NGINX and Gunicorn.
I was wondering what they actually do and why both are used in parallel. What is the purpose of running them both in parallel?
They aren't used in parallel. NGINX is a reverse proxy. It's first in line. It accepts incoming connections and decides where they should go next. It also (usually) serves static media such as CSS, JS and images. It can also do other things such as encryption via SSL, caching etc.
Gunicorn is the next layer and is an application server. NGINX sees that the incoming connection is for www.domain.com and knows (via configuration files) that it should pass that connection onto Gunicorn. Gunicorn is a WSGI server which is basically a:
simple and universal interface between web servers and web applications or frameworks
Gunicorn's job is to manage and run the Django instance(s) (similar to using django-admin runserver during development)
The contrast to this setup is to use Apache with the mod_wsgi module. In this situation, the application server is actually a part of Apache, running as a module.
Nginx and Gunicorn are not used in parrallel.
Gunicorn, is a Web Server Gateway Interface (WSGI) server
implementation that is commonly used to run Python web applications.
NGINX is a free, open-source, high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server.
Nginx responsible for serving static content, gzip compression, ssl,
proxy_buffers and other HTTP stuff.While gunicorn is a Python HTTP server that interfaces with both nginx and your actual python web-app code to serve dynamic content.
The following diagrams shows how nginx and Gunicorn interact.