In this guide, we will deploy Django with Dokku on a VPS with Ubuntu 19.04 installed. Dokku functions a bit like the PaaS solution, Heroku, but in this case, you are hosting it on your own VPS. Dokku is powered by Docker. If you don’t have a VPS with at least 1GB of RAM, you will need to use Swap to get it all to work. If you don’t do this, you will get a lot of errors.
If you have ever used Heroku, then you know that the incredible easy workflow comes with a cost. In many cases, the benefits outweigh the cost, but if you have a very small project, Dokku might just be right for you. It’s fairly easy to set up and you only pay for your VPS.
- A VPS with at least 1GB RAM running Ubuntu 19.04
- A Django project that uses Git for version control (in this tutorial we will use the project name: prdjango)
Let’s create and log in as a new user and install a few required libraries:
Let’s install Dokku #
Download the install file and execute it.
You will probably have to enter your password now. The process of installing Dokku can take a few minutes.
When you got your server, you will also get an IP address (something similar to:
203.0.113.23). Once the installation has been completed, type the IP address in your web browser and you should be welcomed by a setup form from Dokku.
This page will ask you for your public ssh key, but we don’t have that yet. To create such a key, do the following:
It will ask you immediately where you would like to store the ssh key. If you have never run the previous command before, just press enter. The default one is good enough. If you have run the command before, just change the last part of the path. The next question is to set a passphrase. It’s highly recommended to do this. Please remember this one, as you will have to type it in every time you want to deploy your code on the server.
Once you complete that, you will get some more information about the whereabouts of your keys and the fingerprint. To complete the server setup, we need the path to the public key
id_rsa.pub (if you changed the name, it will be different for you). Open the file in a text editor and copy all of its content. Paste the content in the public access part of your website. If the mash of characters starts with
ssh-rsa and ends with your PC’s name, then you got it right!
Up next, fill in your IP address in the
hostname field and uncheck
Use virtualhost naming for apps. Your app URL should look similar to:
http://203.0.113.23:<app-port>. Complete the process by clicking on “Finish Setup”. If all went well, you will be redirected to the official Dokku docs. Dokku is now ready to be used.
Prepare your Django project for deployment #
Let’s go back to your Django project. We need to create a
requirements.txt file to let Dokku know what packages need to be installed. We can create that based on what packages are currently installed in our environment with this command:
Up next, add a new
dokku folder in the root of your project. Then add these files in that folder:
The check file will check if your website still works once you deploy a new version. It will check this right before Dokku pushes your website live. We will leave this file empty for now, Dokku will only run the default checks.
This file will tell Dokku how many processes it should run. If you only plan to use a web process, then you can simply add
web=1 in this file. When you need more processes, you can simply up the number. If you also have async tasks or scheduled tasks in your Django project (like celery) then you will need to add
worker=1 for async tasks and
beat=1 for scheduled tasks.
This is the file that will tell Dokku what to run. We will use uwsgi to run this Django project, but you can use gunicorn as well if you want. Our Procfile should look like this (replace
If you don’t have scheduled celery tasks, you can remove the line starting with
beat. If you don’t use celery or any worker process at all, you can remove the line starting with
worker as well. The web one is mandatory to get your website up and running.
In the previous code block, we refer back to a
uwsgi.ini file to run uwsgi. This will have all the configuration options of uwsgi. You can use this one:
Don’t forget to change
prdjango.wsgi to your project’s name.
This is the last file in this folder. This file is optional, but it’s recommended to use it to add extra commands to your deployment process. In this case, we will add a command to run migrations when a new version has been deployed. Here is the config:
Finally, we need add one more file to the root of your project called ‘Dockerfile`. This file will tell Dokku what to do to deploy a project. Here is an example file of that:
Create a Dokku project and install dependancies #
We have our Django project ready now, and the last thing to do is prepare our server for this specific project. Jump back to your server and let’s install all Dokku dependencies.
The Postgres database, Redis (skip this if you are not using it for cache or celery) and Let’s Encrypt (skip this if you don’t want to use Let’s Encrypt):
Docker works with containers, and since Dokku is based on Docker, it does that too. We will need to create a container for every separated part. In this case, we will have to create one for the Django project itself, the database, and one for Redis (if you are using that).
Create the Django project container:
Create the Django database container:
Create the Redis container (skip this if you are not using Redis):
Up next, we need to connect all the containers so they can communicate. Dokku containers are, by default, completely isolated.
Link the project to the database:
Link the project to redis:
We do not have to link Redis to our Postgres database as they will never directly communicate. This will always be done through your code.
Let’s deploy #
Okay, your server is ready for your project. Let’s put the final touches on your local environment. Go back to your local PC now and run the following:
That’s connects our git repository to the VPS. Up next, let it deploy:
You will have to use the last command every time when you want to deploy a new version of your app. As you will see, it will ask for the passphrase you entered previously.
The last few lines should look like this:
If you don’t see any errors, you should have a fully functional website when you enter your IP address (including the port number!) in your web browser. If you do get an error, make sure you added your IP address to your
ALLOWED_HOSTS variable in your settings file.
If that didn’t solve it, take a quick look at your log files. You can find them by typing
sudo dokku logs prdjango on your server. Again, remember to replace
prdjango with your project name.
Using a domain name instead of an IP address #
Okay. Now, let’s use a domain name for that instead of that ugly and unmemorable IP address.
On your server do:
We will need to edit our settings file. Change
ALLOWED_HOSTS, and replace the IP address with your domain name. Then redeploy your app using the
git push dokku master command. At last, go to your DNS provider (probably where you bought your domain) and point an A record from yourdomain.com and www.yourdomain.com to your IP address. When you check your domain in your web browser, you should have a fully functional website live.
But… it’s not secured yet. Let’s fix that with Let’s Encrypt (it’s free).
Let’s Encrypt will expire every 3 months. The cron job will make sure that it gets renewed before it expires, so your site stays secure.
Some final notes:
- It’s best practice to use a separate settings file in your Django project for local development. You can run that by adding
--settings=local-settings.py. That way you don’t have to change anything in your settings files to keep both the local and live version running. If you don’t have many settings, you can also use environment variables (see point 2).
os.environ.get("DATABASE_URL", "")to get the database URL to be used in your settings file. It’s not recommended to hardcode such a URL in your settings.
- Dokku is great for small scale projects. Dokku is not good for larger projects. It’s much harder to scale and doesn’t have an option to use high-availability for example.
- Also don’t forget to set up a firewall and only allow port 443 and perhaps port 80 and 25. Installing Fail2ban is also a good idea to stop bots from trying to breach through SSH.