Skip to main content

Digital Ocean

This guide can also help you deploy projects on other VPS like Linode, AWS EC2

Introduction

This deployment method is inspired by Cookiecutter Django

I optimized it for some people who are new to Docker and Docker Compose

Prerequisite

The VPS should have Docker and Docker compose installed, Docker pre-installed

  1. Please config DNS record to point to the IP of the VPS.
  2. Please replace domaie name and email name in compose/production/traefik/traefik.yml to match your Domain and your email.

Setup App

SSH to the VPS

# clone the code in /app
(server)$ git clone {GIT_REPO_SSH_URL} /app

# this directory contains DB data
(server)$ mkdir /app/postgres_data && chmod 777 /app/postgres_data

# this directory contains DB backup files
(server)$ mkdir /app/postgres_backup && chmod 777 /app/postgres_backup

# this directory contains media files
(server)$ mkdir /app/media && chmod 777 /app/media

ENV variable

Create .env.production at /app directory

You can check Sample env file for Production

Build

(server)$ cd /app

# wait for some mins
(server)$ docker compose -f production.yml build
(server)$ docker compose -f production.yml up
caution

If you are using old version of Docker Compose, please use docker-compose instead of docker compose

If no error raised, you should be able to visit https://example.com/

Press Ctrl+c to stop the running containers.

# check again
(server)$ docker compose -f production.yml ps

Rather than manually running the containers, let's let Supervisor handle this for us.

Process Manager

Start by installing Supervisor:

(server)$ apt-get update
(server)$ apt-get install -y supervisor

Next, add the following config to /etc/supervisor/conf.d/django_project.conf:

[program:django_project]
directory=/app/
command=docker compose -f production.yml up
autostart=true
autorestart=true
redirect_stderr=true

stdout_logfile=/var/log/supervisor/%(program_name)s_stdout.log
stdout_logfile_maxbytes=5MB
stdout_logfile_backups=5

stopwaitsecs=15
stopasgroup=true

Restart:

(server)$ supervisorctl

supervisor> reload
Really restart the remote supervisord process y/N? y
Restarted supervisord

supervisor> status
django_project STARTING

Now the containers should automatically run on boot. We can also restart the containers via the supervisorctl restart django_project command.

Useful Commands

# To create a superuser
$ docker compose -f production.yml run --rm django python manage.py createsuperuser

# Enter shell
$ docker compose -f production.yml run --rm django python manage.py shell

Auto Deploy in CI

SaaS Hammer already supports this feature and you can check .github/workflows/deploy.yml

Let's create SSH key pair which are used only for deployment.

$ ssh-keygen -t rsa -b 4096 -C "deploy@saashammer.com"

# you will get files
id_rsa id_rsa.pub

Add the id_rsa.pub to user on the server

cat ~/.ssh/id_rsa.pub | ssh USER@HOST "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Add the id_rsa.pub as Deploy key on Github

https://docs.github.com/en/developers/overview/managing-deploy-keys

Config id_rsa as ssh KEY in Github action secrets.

So in Github action, SSH will use the private ssh key id_rsa to login VPS, and then keep using it to pull code.

You should also add HOST, PORT, UERNAME to make the SSH login work. It is recommended to check .github/workflows/deploy.yml to know more details.

And then build image and restart the app via supervisorctl