Voltage

Voltage

Dec. 17, 2023, 8:55 a.m.

Deploying Django, Django Channels, Redis and Celery to production in Railway.

Introduction

After series of dissapointments on deploying Django and other associated services to Railway.app, I finally came up with a solution that may help fellow developers easily deploy their application on Railway with all these services up and running.

Django is an open source python based web framework that is used to build and deploy full stack web applications using Python as a backend programing language. 

Django has tones of packages that developers may use to accomplish their goals. These packages are such as the Django allauth used for authentication, Celery used to manage synchronous tasks, Channels used to manage live updates and message brodcasting using sockets and so on. 

Some of the Django packages may not require extra efforts to deploy since they do not need extra setup outside the provided Django codebase. Perhaps you just make a few tweaks on the settings.py file to make them ready to use.

However, certain packages require extra setup. Packages like Django Channels and Celery may even require additional commands to get them up and running. Most importantly, these commands may be run parrallel to the may Django thread to make the project work well and as expected.

For instance in Development, you may have to run:

python manage.py runserver

to run the Django python development server as well as:

 celery -A project_name.celery worker

to start the celery worker. Assuming that perhaps  your celery worker is used to send emails at the background using Amazon Web services SES, you have to run that command, otherwise, even important emails such as the Account email confimations may fail to be delivered.

So in this blog, I want to assume that you already have a Django project set up corrrectly. You have configured the Consumers and the asgi.py for your channels and that you are able to make websocket connections in development precisely over http.

I also assume that you have already setup your Django celery and that you have tasks and workers well setup and Redis server for local development and that you are just waiting to take the application live.

Setting up Procfile

In most Platform as a service (PaaS) cloud computing services such as Heroku and Railway, we use additional files Procfile, requirements.txt and runtime.txt to configure the startapp commands to be executed during deployment, install packages and configure python version to use respectively.

If you are on linux compter, these files can be created in a manner below on your terminal on you project directory.

touch Procfile
pip freeze > requirements.txt
touch runtime.txt

 These commands are exectued one at a time.

Now in your Procfile, add the following settings.

release: python manage.py makemigrations && python manage.py migrate
web: daphne project_name.asgi:application --port $PORT --bind 0.0.0.0 -v2
celery: celery -A project_name.celery worker --pool=solo -l info

The first line in the Procfile tells the deployment compiler to run migrations  first and keep your database up to date with the changes you made locally.

The second command sets up Daphne a backend server that will be used to run your application over asgi instead of wsgi. This will permit the channels to work flowlessly. It is important to note Channels may work fine over http during development, however in production, it may fail to work. So you have to configure tha routes to use wss in production instead of wss. For instance, in my javascript code at the frontend that takes care of websockets, I will have a configuration like the one below.
 

const chatSocket = new WebSocket(
'wss://' +
window.location.host +
'/wss/chat/' +
boxName +
'/'
);

Instead of :

const chatSocket = new WebSocket(
'ws://' +
window.location.host +
'/ws/chat/' +
boxName +
'/'
);

 This will make channels work over https instead of http. In development to avoid modifying these line every now and again, you can use ngrok to access and develop your website over https. This will lower pain encountered during deployment.

Now in your rerquirements.txt files, you should be having all the list of dependencies used in your peoject. The structure of the requirements.txt may be as below.

certifi==2023.7.22

cffi==1.15.1

channels==4.0.0

channels-redis==4.1.0

chardet==5.2.0

charset-normalizer==3.2.0

click==8.1.7

click-didyoumean==0.3.0

click-plugins==1.1.1

click-repl==0.3.0

constantly==23.10.4

cookiecutter==2.3.0

cryptography==41.0.7

Lastly, in your runtime.txt, you should specify the python version to be used for your project for instance in your runtime.txt, just add the line to use python version 3.10.11. Don't add python versions carelessly, confirm the correct version you have used for development.

3.10.11

 It is also recommended that you setup and use Redis as a message broker for both celery and Channels. To use Redis as a message broker using Railway, go to railway Dashboard, navigate to the repective project and click on the [+ New] button, then add Redis as one of the services.

Once you are ready, you should configure your channel_layers for Channels as below in your settings.py

CHANNEL_LAYERS = {
'default': {
'BACKEND': "channels_redis.core.RedisChannelLayer",
'CONFIG' : {
"hosts":[config("REDIS_HOST_URL")]
},
"symmetric_encryption_keys": [config("DJANGO_SECRET_KEY")],
},
}

The host url will be given to you once you set up  Redis on Railway. Use python Decouple to also manage environmental variables.

On the other hand, set up celery to use redis url as well.

CELERY_BROKER_URL = config("REDIS_HOST_URL")

CELERY_RESULT_BACKEND = config("REDIS_HOST_URL")

When all these are well setup, push your code to Github once the push is complete, head over to Railway, set up new project and deploy your code from the github repository you pushed your application on. You shall have successfully deployed Redis, Channels, Django and Celery all at the same time to Railway.app.

 

Feel free to reach out via email: [email protected] if you need help. I understand how brief and technical this blog is for junior developers.