I'm going to make a bold statement: Django replaced Ruby on Rails in the hearts of many developers. With this increase in popularity, we've seen tons or articles, videos and websites dedicated to setting un Django and creating apps using the framework.
Unfortunately, when it comes to deployment, many of these resources only mention heroku or pythonanywhere. While these are excellent solutions for quickly shipping your MVP or prototype, it lacks a bit in terms of flexibility if you want to create your custom deployment pipeline.
tl-dr: If you manage your own server infrastructure, we're going to setup a git deployment workflow with django
What you'll need
- Working knowledge of ssh
- Working knowledge of git
- Working knowledge of the bash shell
- Basic linux command line skills (sorry hipsters)
- (Very) Basic knowledge of vi/vim
- Patience
The typical workflow usually looks like this:
- You have your development environment, either on your local machine or a remote server
- A git server (on GitHub, BitBucket, GitLab ...) that you and your team push your work to
- A production server (aka your live app).
Usually when you commit and push work you do something like:
origin
being the name of the remote server your code is being pushed to. What took me a while to realise is that you can have many remotes for your repo that point to different servers.
The idea here is to add a new remote to our repo. It will point to our production server such that when we run git push live master
, our code will be copied over to there.
On the production server
To achieve this, we have some setup work to do on our live server. So go ahead and connect to it via ssh.
# If your server's ssh service listens on a port other than 22, you'll need
# to add the -p switch
Once we're in, we need to create a new directory for our application. This is where our deployed code will be copied to.
# Some people prefer to use /var/www/<project_name>, it's really up to you. Just
# make sure remember the path to your project
Now head over to /var
and create another directory called repos
# Depending on your setup, you might need sudo priveleges
Inside that directory, we need to create a folder named after our project (or domain name) and append it with .git
(not necessary but it's good practice)
Inside this folder we'll create what is called a bare
repository. To do this just run:
If you run ls
inside that folder you'll see a bunch of files and directories (the same ones found inside the .git
folder in normal repos). One of these directories is called hooks
.
Inside that folder, we'll need create a file called post-receive.
# Assuming you are inside /var/repos/yourproject.git
Now open it up with vi/vim
Hit i
to switch to insert mode, and add the following to the file:
#!/bin/bash
DEPLOYDIR=/home/username/sites/myawesomedjangoproject # or whatever path you chose
GIT_WORK_TREE=""
Please note that the first shebang line is important, it instructs git to use bash instead of the default shell. Otherwise it won't activate our (soon to be created) virtual environment
exit vim by hitting :wq
(which in vim lingo means write and quit)
What we've done here is set two variables. DEPLOYDIR
is an alias for our project path on the server, and GIT_WORK_TREE
which is a special variable that tells git to copy the code it receives inside of our DEPLOYDIR
. This ensures that we're always running the latest version of our code.
As you've probably noticed, this post-receive file looks very much like a shell script. That's because it is (as explained above). It's executed every time you push code to the repo.
The last thing we need to is make the script executable, so as soon as you're back in the shell run:
You can now exit the server and go back to your local machine.
On our local dev environment
Now that we've created our remote repository, we need to add it to our project (I like to call mine live
).
It takes one simple command:
# And if your server's ssh service listens on a different port :
To make sure it was added, you can print the list of available remotes by running:
and that's it ! You can now make changes locally, commit and deploy them live (or staging if it's a staging server) and see your changes instantly.
You can obviously still push to github/lab or bitbucket with git push origin <branch>
like you normally would.
Bonus
As I mentioned in the first part, the post-receive hook is a shell script. Which means you can use it to perform all kinds of tasks against your code, like running front-end builds, installing dependencies, etc ...
Here's an example for a basic Django App:
#!/bin/bash
DEPLOYDIR=/home/username/site/myawesomedjangoproject
GIT_WORK_TREE=""
if
I run my Django Apps as systemd services, if you don't you can just call python manage.py runserver. If you want to know how to setup Django the way I do just follow this very comprehensive tutorial over on Digital Ocean
Conclusion
I am fully aware that there are more sophisticated methods of deployment through Docker, Travis (For continious integration) etc. But if you have a small app that you want to ship and you already have an infrastructure, I've found this method to be more than suitable.
Please report any missing info, mistake, error, typo. I'm on twitter if you wanna chat.