Hang tight as I will teach you how to deploy Django Channels fast. Django Channels is a package for allowing WebSockets and other asynchronous protocols to be used in a Django application. It is built on top of the Django web framework and allows for the creation of real-time applications such as chat applications, online games, and more. Channels provides a channel layer that acts as a kind of “inbox” for messages that are sent asynchronously between different parts of your application, allowing for more efficient communication between the client and server.
Channels wraps Django’s native asynchronous view support, allowing Django projects to handle not only HTTP, but protocols that require long-running connections too — WebSockets, MQTT, chatbots, amateur radio, and more.
This tutorial will take you through the process of deploying a chat app implemented using Django-channels on the Doprax cloud platform. The process of implementing the chat app can be found in the Django-channels documentation here. You can stop at tutorial 2 in the link.
The Deployment Process
I want to believe we have gone through the tutorial in Django-channels tutorial. To deploy the app that we have implemented locally, there are certain things we have to do. We will first perform these things for Development Purposes and then go on to things to do for production.
Deploy on Doprax for Development purposes
Deploying on Doprax requires us to dockerize our project. So we’re going to create Dockerfile and doprax.yaml file in the project directory.
From the image above. You will notice the name of my Django project is chatProj and I have an app named chat.
In the Dockerfile put the below code.
FROM ubuntu:22.04 RUN apt-get update && apt-get install -y python3 python3-pip python3-venv RUN python3 -m venv chat_env WORKDIR /code # install dependencies COPY requirements.txt /code/ RUN /chat_env/bin/pip install -r requirements.txt # Copy project COPY . /code/ # Expose ports EXPOSE 8000 RUN chmod +x /code/start.sh ENTRYPOINT ["./start.sh"]
So above we are telling docker to:
- Set our base image as ubuntu version 22.04 image.
- Install python3, python3-pip, python3-venv.
- Create a virtual environment named chat_env.
- Create our working directory /code.
- Copy our requirements.txt file into the working directory.
- Install all packages in the requirements.txt file.
- Copy all our folders to the working directory.
- Expose port 8000.
- Execute the instructions in a file named start.sh .
Create start.sh file in your project directory also. Put the below code.
#!/bin/bash source /chat_env/bin/activate cd /code echo "----- Collect static files ------ " python manage.py collectstatic --noinput echo "-----------Apply migration--------- " python manage.py makemigrations python manage.py migrate echo "-----------Run django local server--------- " python manage.py runserver 0.0.0.0:8000
Above we are:
- Activating our environment
- Serving our static files
- Running our migrations
- Running normal runserver command for Django
The reason for running “python manage.py runserver” is that for our WebSocket app to work we need daphne. Daphne is the protocol server for asgi applications that Django channels use. So since we have daphne in INSTALLED APPS in settings.py, it will take over the “python manage.py runserver” command . This is what makes this method of deploying your Django-channels app Development purpose.
In doprax.yaml file, put the below code.
volumes: - name: static mount: /staticfiles/ services: - redis: tag: 5
Above we are:
- Creating volumes named static, where our static files will be persisted.
- Using Redis since the Redis-channel layer is used in our CHANNEL_LAYER_BACKEND as in Django-channels tutorial documentation.
Great! we have set up the important files needed for deployment on doprax. There are just 3 more things to do.
First, in the Django-channels tutorial, in the room.html file, there is a line that establishes a WebSocket connection but uses “ws://” when creating the path. We have to change it to “wss://”. “ws” means “WebSocket” while “wss” means “WebSocket secure”.
The second thing is to go to the settings.py file and change the “host” in the CHANNEL_LAYERS to “redis” instead of “127.0.0.1”. We are doing this because when we add redis service on doprax the hostname will be “redis”.
The third thing is to allow doprax in the ALLOWED_HOST setting in the settings.py file. You can do that by putting ‘*’, meaning allow all, or ‘.doprax.com’, meaning allow only those with doprax.com domain.
We are done! Now push your code to GitHub and head over to the Doprax cloud platform.
Doprax platform
Doprax is a cloud platform for hosting your websites, apps, and APIs.
Create your account on Doprax and head to the Account section and connect your GitHub account.
Create an App by heading to the Dashboard section and clicking NewApp Give it a title and Description.
Click on the created app and click on import from my GitHub account.
Import the repository you created on your GitHub.
After importing your code from GitHub you will notice there is a message saying “doprax.yaml dependency file detected. Do you want to create dependencies created in it?”. Click Yes create them.
Go to the Services section. You will notice Redis is automatically set up for you. This is because we allowed Doprax to create the dependencies in doprax.yaml file.
Now go to the Volumes section, and you will also notice it is automatically set.
Finally, head to the Deploy section and press the play button.
Deploy on Doprax for Production purposes
In this part, we will use supervisor, Nginx to ensure gunicorn and daphne work properly.
Supervisor is a client/server system that allows its users to control a number of processes on UNIX-like operating systems. It will help start and manage gunicorn and daphne for our chat app.
Nginx is a web server that can also be used as a reverse proxy, load balancer, mail proxy and HTTP cache. It will act as our load balancer, it will route HTTP requests to gunicorn and WebSocket requests to Daphne.
With that understanding; we will create Dockerfile in the project directory to dockerize the app, create doprax.yaml since doprax uses it to set up volumes and services automatically for us, create various .sh and .conf files to make sure daphne and gunicorn works.
In your Dockerfile add the below code
FROM ubuntu:22.04 RUN apt-get update && apt-get install -y python3 python3-pip python3-venv supervisor ARG USER=root USER $USER RUN python3 -m venv chat_env WORKDIR /code # install dependencies COPY requirements.txt /code/ RUN /chat_env/bin/pip install -r requirements.txt # Copy project COPY . /code/ COPY deployment deployment COPY deployment/gunicorn.conf /etc/supervisor/conf.d/gunicorn.conf COPY deployment/daphne.conf /etc/supervisor/conf.d/daphne.conf RUN mkdir /logs # Expose ports EXPOSE 8000 EXPOSE 8001 RUN chmod +x /code/start.sh RUN chmod +x /code/deployment/start_app.sh RUN chmod +x /code/deployment/start_daphne.sh ENTRYPOINT ["./start.sh"]
So in the above, we are telling docker to:
- set our base image as ubuntu version 22.04 image.
- install python3, python3-pip, python3-venv and supervisor
- setting user as root
- create a virtual environment named chat_env.
- create our working directory /code.
- copy our requirements.txt file into the working directory.
- install all packages in the requirements.txt file.
- copy all our folders to the working directory.
- copy deployment folder to deployment
- copy the config files in the deployment folder to the conf.d folder after supervisor is installed.
- create logs directory. This is to keep log files of daphne and gunicorn
- expose port 8000 (for gunicorn)
- expose port 8001(for daphne)
- Give permissions for executing the .sh files.
- execute the instructions at the start.sh file.
In your start.sh file add the below code.
#!/bin/bash exec /usr/bin/supervisord -n
Above we are starting supervisor.
In your doprax.yaml file add the below code
volumes: - name: static mount: /staticfiles/ services: - redis: tag: 5
Above we are:
- Creating volumes named static, where our static files will be persisted.
- Using Redis since the Redis-channel layer is used in our CHANNEL_LAYER_BACKEND as in Django-channels tutorial documentation.
Now create deployment folder in your project directory and create the following files; daphne.conf, gunicorn.conf, start_app.sh, start_daphne.sh
So what we are doing is creating conf files for daphne and gunicorn which supervisor will use. The start_app.sh file contains the command to start gunicorn while start_daphne.sh file contains the command to start daphne.
In gunicorn.conf file add the below code
[program:gunicorn] command=/code/deployment/start_app.sh directory=/code/chatProj user=root autostart=true autorestart=true redirect_stderr=true stdout_logfile = /logs/gunicorn.log
Above we are:
- Creating a supervisor program and calling it gunicorn
- Telling supervisor the command to run to start gunicorn program. The command is in the start_app.sh file
- Defining directory of our project
- Setting user as root
- Telling supervisor to autostart and autorestart the program
- Defining where logs to go to
In daphne.conf add the below code
[program:daphne] command = /code/deployment/start_daphne.sh directory=/code/chatProj user = root autostart=true autorestart=true stdout_logfile = /logs/daphne.log redirect_stderr = true
Above we are:
- creating a supervisor program and calling it daphne
- telling supervisor the command to run to start daphne program. The command is in the start_daphne.sh file
- defining directory to our project
- setting user as root
- telling supervisor to autostart and autorestart the program
- defining where logs to go to
In start_app.sh add the below code
#!/bin/bash source /chat_env/bin/activate cd /code echo "----- Collect static files ------ " python manage.py collectstatic --noinput echo "-----------Apply migration--------- " python manage.py makemigrations python manage.py migrate echo "-----------Run gunicorn--------- " gunicorn -b :8000 chatProj.wsgi:application
In start_daphne.sh add the below code
#!/bin/bash source /chat_env/bin/activate cd /code daphne -b 0.0.0.0 -p 8001 chatProj.asgi:application
So we have done the major work of starting gunicorn and daphne and it is managed by supervisor
What remains is our nginx acting as a load balancer. We are going to setup on doprax as a service
Now push what you have done to GitHub and head over to the Doprax cloud platform.
Nginx on the Doprax platform
Follow the processes in the Doprax Platform section of this tutorial. After importing your code repository and allowing doprax to create dependencies in doprax.yaml.
Head over to Services. Click on Add a service. Click on Nginx and click add.
Now click on + sign in mounted config files
A box will show. Now add what you see in the image below and press create
It is time to write in the nginx.conf file. Click on the edit file in the mounted config files part of the nginx service.
worker_processes 8; user root; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events {} http { include mime.types; server { listen 80; server_name chat-appmjjg.eu-ccofhtfzmvsd.dopraxapp.com; #it should correspond to the one in deploy section for your app gzip on; gunzip on; gzip_types text/plain text/css text/js text/xml text/javascript application/javascript application/json application/xml application/rss+xml image/svg+xml; location / { proxy_pass http://main:8000; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; } location /static/ { alias /staticfiles/; } location ~^/ws/ { proxy_pass http://main:8001; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_connect_timeout 70s; proxy_send_timeout 70s; proxy_read_timeout 70s; } } }
So if you notice in the code where location / is defined, the requests are proxy passed to gunicorn i.e http://main:8000;
For location ~^/ws/, requests are proxy passed to daphne i.e http://main:8001;
So that is all. Head to the Deploy section and press the play Button.
Hurray, chat app is deployed and running!