Deploying Django Channels: how to keep Daphne running after exiting shell on web server
Asked Answered
A

2

7

As practice, I'm trying to deploy Andrew Godwin's multichat example with Django Channels 2.1.1 on DigitalOcean Ubuntu 16.04.4. However, I don't know how to exit the Ubuntu server without Channels' Daphne server stopping.

Right now, almost my entire familiarity with deployment comes from this tutorial, and that's how I've deployed the site. But according to Channels' documentation, I have to run one of these three in production to start Daphne:

  • daphne myproject.asgi:application
  • daphne -p 8001 myproject.asgi:application
  • daphne -b 0.0.0.0 -p 8001 myproject.asgi:application

So, in addition to following the DigitalOcean tutorial, I ran these also. The third one worked for me and the site ran well. However, if I exit shell on Ubuntu, Daphne stops too.

The tutorial has gunicorn access a sock file (--bind unix:/home/sammy/myproject/myproject.sock), and in my research so far I've seen on a few sites published before 2018 that somehow somewhere a daphne.sock file is generated. So, I guess Channels deploys similarly? But I haven't seen any details about how this is done.

How do I deploy the multichat example so I can exit the Ubuntu web server without Daphne stopping?

Update 6 May 2018, 8pm CET:

I tried kagronick's solution below and created a systemd file at /etc/systemd/system/daphne_seb.service:

[Unit]
Description=daphne daemon for seb
After=network.target

[Service]
User=root
Group=www-data
WorkingDirectory=/home/seb/seb
ExecStart=/home/seb/env_seb/bin/python /home/seb/seb/manage.py daphne -b 0.0.0.0 -p 8001 multichat.asgi:application
Restart=on-failure

[Install]
WantedBy=multi-user.target

I did systemctl daemon-reload and systemctl start daphne_seb.service and it ran for a couple of seconds. Then, systemctl status daphne_seb.service said Unknown command: 'daphne'.

I tried restarting it. Then I rebooted the OS. Now status says:

daphne_seb.service - daphne daemon for seb
   Loaded: loaded (/etc/systemd/system/daphne_seb.service; enabled; vendor preset: enabled)
   Active: inactive (dead) (Result: exit-code) since Sun 2018-05-06 19:33:31 UTC; 1s ago
  Process: 2459 ExecStart=/home/seb/env_seb/bin/python /home/seb/seb/manage.py daphne -b 0.0.0.0 -p 8001 multichat.asgi:application (code=exited, status=1
 Main PID: 2459 (code=exited, status=1/FAILURE)

May 06 19:33:31 ubuntu-s-1vcpu-1gb-ams3-01 systemd[1]: daphne_seb.service: Main process exited, code=exited, status=1/FAILURE
May 06 19:33:31 ubuntu-s-1vcpu-1gb-ams3-01 systemd[1]: daphne_seb.service: Unit entered failed state.
May 06 19:33:31 ubuntu-s-1vcpu-1gb-ams3-01 systemd[1]: daphne_seb.service: Failed with result 'exit-code'.
May 06 19:33:31 ubuntu-s-1vcpu-1gb-ams3-01 systemd[1]: daphne_seb.service: Service hold-off time over, scheduling restart.
May 06 19:33:31 ubuntu-s-1vcpu-1gb-ams3-01 systemd[1]: Stopped daphne daemon for seb.
May 06 19:33:31 ubuntu-s-1vcpu-1gb-ams3-01 systemd[1]: daphne_seb.service: Start request repeated too quickly.
May 06 19:33:31 ubuntu-s-1vcpu-1gb-ams3-01 systemd[1]: Failed to start daphne daemon for seb.

I checked the filepaths. They're correct. I also tried adding Environment=DJANGO_SETTINGS_MODULE=multichat.settings, which I saw here. But that didn't help either.

Update 6 May 2018, 10pm CET:

Then, I read here that only 5 restarts are allowed within a 10-second period. So I removed Restart=on-failure to start the service myself.

This brought me back to Unknown command: 'daphne'. This solution suggested to me that I shouldn't be pointing to Python but to Daphne in my virtualenv, so I changed it: ExecStart=/home/seb/env_seb/bin/daphne. I also removed /home/seb/seb/manage.py based on the same solution. This gave me a new problem:

daphne_seb.service - daphne daemon for seb
   Loaded: loaded (/etc/systemd/system/daphne_seb.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Sun 2018-05-06 19:55:24 UTC; 5s ago
  Process: 2903 ExecStart=/home/seb/env_seb/bin/daphne daphne -b 0.0.0.0 -p 8001 multichat.asgi:application (code=exited, status=2)
 Main PID: 2903 (code=exited, status=2)

May 06 19:55:24 ubuntu-s-1vcpu-1gb-ams3-01 daphne[2903]:               [-v VERBOSITY] [-t HTTP_TIMEOUT] [--access-log ACCESS_LOG]
May 06 19:55:24 ubuntu-s-1vcpu-1gb-ams3-01 daphne[2903]:               [--ping-interval PING_INTERVAL] [--ping-timeout PING_TIMEOUT]
May 06 19:55:24 ubuntu-s-1vcpu-1gb-ams3-01 daphne[2903]:               [--application-close-timeout APPLICATION_CLOSE_TIMEOUT]
May 06 19:55:24 ubuntu-s-1vcpu-1gb-ams3-01 daphne[2903]:               [--ws-protocol [WS_PROTOCOLS [WS_PROTOCOLS ...]]]
May 06 19:55:24 ubuntu-s-1vcpu-1gb-ams3-01 daphne[2903]:               [--root-path ROOT_PATH] [--proxy-headers]
May 06 19:55:24 ubuntu-s-1vcpu-1gb-ams3-01 daphne[2903]:               application
May 06 19:55:24 ubuntu-s-1vcpu-1gb-ams3-01 daphne[2903]: daphne: error: unrecognized arguments: multichat.asgi:application
May 06 19:55:24 ubuntu-s-1vcpu-1gb-ams3-01 systemd[1]: daphne_seb.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
May 06 19:55:24 ubuntu-s-1vcpu-1gb-ams3-01 systemd[1]: daphne_seb.service: Unit entered failed state.
May 06 19:55:24 ubuntu-s-1vcpu-1gb-ams3-01 systemd[1]: daphne_seb.service: Failed with result 'exit-code'.

I check my multichat.asgi:application and it's in the right place. So I can't figure out why it says error: unrecognized arguments: multichat.asgi:application.

Aleece answered 5/5, 2018 at 18:51 Comment(0)
A
2

My question is in fact the same as this one. Questions like that usually get sent to this solution. I did not recognise the question as the same as mine at first because (i.) I wasn't familiar with the vocabulary of deployment with Channels yet and (ii.) a lot of these questions and their solutions mention things that have already been deprecated for Channels 2. I've lost the page but, for instance, Channels 2 doesn't require us to do python manage.py runworker.

There's also the issue of upstart and systemd. Several solutions use an upstart script. But, I had a vague sense that maybe if I'm on Ubuntu 16.04.4, I should use systemd. I did a google and found that systemd had indeed replaced upstart, according to articles like this one.

@kagronick provides the correct systemd solution, but I had to edit it to make it work for me:

# /etc/systemd/system/daphne_seb.service

[Unit]
Description=daphne daemon for seb
After=network.target

[Service]
User=root
Group=www-data
WorkingDirectory=/home/seb/seb
ExecStart=/home/seb/env_seb/bin/daphne -b 0.0.0.0 -p 8001 multichat.asgi:application

# I turned this off for testing purposes.
# Still not sure if should use 'on-failure' or 'always'. 
# Restart=on-failure

[Install]
WantedBy=multi-user.target

And then in shell:

systemctl daemon-reload
systemctl start daphne_seb.service
Aleece answered 7/5, 2018 at 0:1 Comment(0)
M
9

I use systemd for it. You would set a unit file in /etc/systemd/system/daphne.service

with contents like:

[Unit]
Description=My Daphne Service
After=network.target

[Service]
Type=simple
User=wwwrunn
WorkingDirectory=/srv/myapp
ExecStart=/path/to/my/virtualenv/bin/python /path/to/daphne -b 0.0.0.0 -p 8001 myproject.asgi:application
Restart=on-failure

[Install]
WantedBy=multi-user.target

I have all the parts of my application configured this way. It allows them to resume if they ever crash. Systemd can handle all the logging. And they are all started in the right order. Use Type=simple so you don't need to do any forking or writing of PID files. It will just manage the one process. I run a few of these to spread out the load.

After you put this file in place you would run the following commands:

Make the system aware of the service

sudo systemctl daemon-reload

Start the service

sudo systemctl start daphne.service

Make it run on reboot

sudo systemctl enable daphne.service

You will need to edit some of the parameters to fit your needs. If you called the file something other than daphne.service you'll need to change it in the commands. The ExecStart line will need to be changed to your python path and the namespace where your application lives.

Your logs will now show up in journalctl. To see logs for this service you would do journalctl -u daphine.service. If you want to tail the logs put -f at the end for "follow". journalctl has a bunch of options that you can find with --help or by looking up resources online. The same goes with systemd unit files.

Of course you should know that Daphine shouldn't be exposed directly to the web. Nginx, Apache, or another web server should be proxying to Daphne and serving your static assets. (You could also use a CDN for that)

Mack answered 6/5, 2018 at 17:44 Comment(4)
Hey, thanks for the solution. systemctl status daphne.service says "Unknown command: 'daphne'". I checked my filepaths, they're correct. Any idea what could be the matter?Aleece
I've updated my question. It now stops with Start request repeated too quickly.Aleece
I worked it out, thanks in part to your help. Will write out a complete solution after dinner. Thank you!Aleece
To make it auto start when system startup sudo systemctl enable daphne.serviceCand
A
2

My question is in fact the same as this one. Questions like that usually get sent to this solution. I did not recognise the question as the same as mine at first because (i.) I wasn't familiar with the vocabulary of deployment with Channels yet and (ii.) a lot of these questions and their solutions mention things that have already been deprecated for Channels 2. I've lost the page but, for instance, Channels 2 doesn't require us to do python manage.py runworker.

There's also the issue of upstart and systemd. Several solutions use an upstart script. But, I had a vague sense that maybe if I'm on Ubuntu 16.04.4, I should use systemd. I did a google and found that systemd had indeed replaced upstart, according to articles like this one.

@kagronick provides the correct systemd solution, but I had to edit it to make it work for me:

# /etc/systemd/system/daphne_seb.service

[Unit]
Description=daphne daemon for seb
After=network.target

[Service]
User=root
Group=www-data
WorkingDirectory=/home/seb/seb
ExecStart=/home/seb/env_seb/bin/daphne -b 0.0.0.0 -p 8001 multichat.asgi:application

# I turned this off for testing purposes.
# Still not sure if should use 'on-failure' or 'always'. 
# Restart=on-failure

[Install]
WantedBy=multi-user.target

And then in shell:

systemctl daemon-reload
systemctl start daphne_seb.service
Aleece answered 7/5, 2018 at 0:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.