1) Deploying Django 2.x with Django Channels 2.x

I will skip how to create a Django Channels 2.x project since this has been covered by the official Django Channels tutorial. If you are looking for examples (specific to Channels 2.x) with a little more meat on them, try:

MultiChat — By Andrew Godwin, the main contributor for Django Channels.

Real-Time Taxi App — By Jason Parent, at TestDriven.io

As you may know, you can configure everything in Elastic Beanstalk through either their online interface or through config files. I will cover how to deploy with the latter, as this is more common practice for production environments. You can just script your deployments and not have to go manually tweak settings every time you upload a new version.

Make sure you are using virtualenv or virtualenvwrapper . Make sure your pip is up to date. Install awsebcli . Start and configure your awsebcli for your project.

(venv)>pip install --upgrade pip

...

(venv)>pip --version

pip 19.1.1 from c:\dev\envs\venv\lib\site-packages\pip (python 3.6)

...

(venv)>pip install awsebcli

...

(venv)>cd path/to/your/project/

(venv)>eb init -v

...

3.1. During the upcoming eb create -v command, you will be asked to define the application, environment, and CNAME for your Elastic Beanstalk. This CNAME will determine the URL that you will use to access the Load Balancer that connects to the EC2 instances. eb deploy -v is what you will use to deploy new versions.

Make sure that the CNAME URL is in your ALLOWED_HOSTS list in your Django settings file. Otherwise, your connection will be rejected.

4. Create a folder called .ebextensions which will house all your Elastic Beanstalk config files. These will determine all the AWS behavior of your deployment and you can find all the information you may need in their official documentation. However, for a simple deployment, make sure you have the following file:

<PROJECT_DIR>/.ebextensions/01_env.config

WSGIPath: Is setting the path to the WSGI file for your Apache config.

DJANGO_SETTINGS_MODULE: Is required to run Django, and this is setting it as an environment variable in the EC2 instance.

PYTHONPATH: Adding the path to the project director to PYTHONPATH.

4.1. If you are doing Option 1 then add the following:

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

What this is doing is telling Elastic Beanstalk to allow the Application Version Elastic Load Balancer (hence elbv2) to listen on port 80 and if a request comes in to a path that matches the following pattern: hostname:80/ws/* then forward it to port 5000 in the EC2 instance it is managing.

Note: It doesn’t have to be port 5000 the one to handle your WebSockets and your path doesn’t have to be /ws/ . Also, your process names and rule names don’t have to be http , websocket , and ws , respectively.

4.2. If you are doing Option 2 or Option 3 then add the following:

option_settings:

...

aws:elbv2:listener:80:

ListenerEnabled: 'true'

Protocol: HTTP aws:elbv2:listener:5000:

ListenerEnabled: 'true'

Protocol: HTTP

This is telling Elastic Beanstalk to allow the Application Load Balancer to listen and forward any request on port 80 and port 5000.

5. Add another config file:

<PROJECT_DIR>/.ebextensions/02_setup.config

00_pip_upgrade: Will upgrade the pip inside the EC2 instance.

01_migrate: Will run your migrations into your connected RDS instances.

02_collectstatic: Will gather your static files, likely into an S3 bucket (see: django-storages)

03_wsgipass: Tells Apache to forward the authorization headers to Django.

6. Finish your deployment and deploy new versions:

...

(venv)>eb create -v

...

(venv)>eb deploy -v

...

Troubleshooting

If anything goes wrong here, you most likely want to SSH into the EC2 instance and check logs directly or get them through the AWS console. If you built everything in a private VPC (common infrastructure for public-facing applications running private servers, databases, and other services) you are going to need to have a Bastion EC2 instance. If that’s the case, you will have to SSH into the Bastion server and from there SSH into your private EC2 instances.

AWS Console -> Elastic Beanstalk -> Application -> Environment -> Request Logs

I’m using PostgreSQL and had an issue during eb create and eb deploy due to the fact that I had psycopg2==2.8.4 and psycopg2-binary==2.8.4 . I’m not sure what the error is in those libraries but downgrading them to 2.7.7 allows for the deployment to continue.

and due to the fact that I had and . I’m not sure what the error is in those libraries but downgrading them to allows for the deployment to continue. The following commands are your friends to diagnose problems in real-time.

$tail -f /var/log/httpd/access_log

$tail -f /var/log/httpd/error_log

$tail -f /var/log/eb-activity.log

If you are using PostgreSQL and need to access the database:

$sudo yum install postgresql

$psql -h <DB HOSTNAME> -d <DB NAME> -U <DB USER>

If you need to play with the Django shell:

$export DJANGO_SETTINGS_MODULE="<PROJECT_DIR...CONFIG.FILE>"

$source /etc/python/run/venv/bin/activate

(venv)$cd /etc/python/current/app/<PROJECT_DIR>/

(venv)$python manage.py shell

If your Elastic Beanstalk status turns to SEVERE shortly after deploying, you may have to configure a different health check path or health check code:

AWS Console -> Elastic Beanstalk -> Application -> Environment -> Configuration -> Load Balancer

2) Connecting Redis as the channel layer

I will assume that you are familiar with the role of the channel layer in Django Channels.

Install channels_redis .

>pip install channels_redis

2. Create a Redis instance through AWS ElastiCache.

3. Add the following to your Django config file:

CHANNEL_LAYERS = {

'default': {

'BACKEND': 'channels_redis.core.RedisChannelLayer',

'CONFIG': {

"hosts": [(<REDIS ELASTICACHE HOSTNAME>, 6379)],

},

},

}

Troubleshooting

Open a Django shell in your EC2 instance and test that your channel layer is working: