One of the most challenging parts in deploying applications in Amazon Web Services (AWS) Elasticbeanstalk (EB) is handling processes that run in the individual instances that live in your cluster. On my end specifically, it was how to deploy Django channels 2 on Elasticbeanstalk through a load balancer.
There were a lot of tutorials/guides on the internet but none really quite helped, the reason being is that most if not all of them use a configuration file geared for Amazon Linux AMI instances, while the latest environment platforms of AWS now use Amazon Linux 2 (AMI 2) instances which have a different configuration and directory structure that renders previous tutorials obsolete. You can read more on how to migrate to AMI 2 here
This tutorial is divided into three parts, feel free to choose the parts where you are more interested in:
Set up assumptions
In order for this tutorial to be effective, I have shared my underlying assumptions below:
You are using an Application load balancer (ALB) routing setup, which just means that all traffic is handled by ALB. Classic load balancers do not support WebSockets, while Network load balancers were not used for this tutorial;
You already have an up and running Django application locally that already runs Django Channels 2;
You have an external Redis instance (Any would do as long as it is accessible through your EB instances);
lastly, you already have the EB Command Line Interface (CLI) installed, if not, you can follow the instructions here
Deploying your application
Once everything is set up, let’s deploy! If you don’t yet have a .ebextensions folder, please do create it in your root directory. Inside, create a config file
01_<your_custom_name>.config and paste the entries below:
option_settings: aws:elbv2:listener:80: DefaultProcess: http ListenerEnabled: 'true' Protocol: HTTP Rules: ws aws:elbv2:listenerrule:ws: PathPatterns: /ws/* Process: websocket Priority: 1 aws:elasticbeanstalk:environment:process:http: Port: '80' Protocol: HTTP aws:elasticbeanstalk:environment:process:websocket: Port: '5000' Protocol: HTTP
This tells our ALB to listen to port 80, and if a path comes in with the pattern
/ws/* pass the request to port 5000 of the instances under EB. Note that port 5000 here is optional and you can use whichever port you want. You can also lookup other rules here
Next, we use a
Procfile to run our processes. Create a file named
Procfile and save it in your root directory, inside paste the following code:
web: gunicorn --bind :8000 --workers 3 --threads 2 <your_app>.wsgi:application websocket: daphne -b 0.0.0.0 -p 5000 <your_app>.asgi:application
Make sure you change
<your_app> to point to your application. Also, note that we have configured our wsgi entry point here rather than in the config file we did above. Lastly, the daphne server port we’re binding should coincide with the one you specified in your ALB config file as this would receive the requests from WebSockets.
Once you enabled https for your application, you would just need to do a minor tweak in your configuration file to listen for
wss connections and pass them accordingly. In the config file you have created previously, just edit the code to look like the following:
option_settings: aws:elbv2:listener:80: DefaultProcess: http ListenerEnabled: 'true' Protocol: HTTP Rules: ws aws:elbv2:listener:443: ListenerEnabled: 'true' Protocol: HTTPS SSLCertificateArns: <YOUR ARN FROM AWS CERTIFICATES MANAGER> SSLPolicy: ELBSecurityPolicy-2016-08 Rules: ws aws:elbv2:listenerrule:ws: PathPatterns: /ws/* Process: websocket Priority: 1 aws:elasticbeanstalk:environment:process:http: Port: '80' Protocol: HTTP aws:elasticbeanstalk:environment:process:websocket: Port: '5000' Protocol: HTTP
This just listens to port 443, then passes WebSocket related path to your instances inside EB as per before. Make sure you replace
<YOUR ARN FROM AWS CERTIFICATES MANAGER> with the actual arn resource from your approved certificates.
There you have it, folks! Hope this guide helped.