Upcloud Server Options

Summary

  • Get a VPS server, I deployed to Upcloud
  • Login to the server and install docker
  • Add Dockerfile, docker-compose.yaml and Github actions to your project
  • Push your project to Github
  • Manually clone the project from the server for the first time
  • Run docker-compose up -d and go have fun. 🚀🚀🚀🚀🚀

Requirements To Get the Best From This Guide

  • A terminal. I love Cmder.
  • A running django project with a requirements.txt. The project I deployed uses postgresQL.
  • Github account
  • A VPS, this guide uses Upcloud.

How to Deploy Django to any VPS Using Docker

The Django Project Structure After Set Up

.
├── APP1
├── APP2
├── APP3
├── THE_USUAL_DJANGO_COMMON_FILES
├── Caddyfile
├── Dockerfile
├── docker-compose.yaml
├── manage.py
├── media
├── postgres
├── Procfile
├── README.md
├── requirements.txt
├── staticfiles

The steps below are for fresh server, for subsequent deployment simply make changes commit and push to the Github repository and you’re done! 🎉

Step 0. ✔ Deploy a Server and Create a User

Go to your VPS provider, open an account and deploy a VPS server of your choice. For example, deploy a $5 server on Upcloud.

Upcloud Server Options

So, for upcloud, create an account, sign in and then deploy a server of your choice like so:

  • Choose a location

Select Upcloud Location

  • Select server plan

Select Upcloud Plan

  • Choose operating system, I prefer Ubuntu

Choose VPS OS

  • Deploy and note down the server IP address and the root password

Choose VPS OS

After deploying the server, from your computer terminal, ssh as root into the server (ssh root@YOUR_SERVER_IP and enter the server password). How to SSH into a Server How to SSH into a Server

Create a new user by running adduser USER_NAME in my case, that is adduser ck

adduser USER_NAME

How to SSH into a Server

Give the new user sudo privileges

usermod -aG sudo USER_NAME

By now, you should have a new user with sudo permission.

Step 1. ✔ How to Install Docker on a VPS in One Simple Script

After you have created a new user above, end the current session by pressing Ctrl + D or by closing the terminal.

Reopen the terminal and ssh into the server as the new user you created by typing ssh USER_NAME@YOUR_SERVER_IP and enter the password you set while creating the user. How to SSH into a Server

Download docker installation script to your server:

curl -fsSL https://get.docker.com -o get-docker.sh

How to SSH into a Server

Install docker:

sh get-docker.sh

Modify permissions:

sudo usermod -aG docker USER_NAME

How to SSH into a Server

When you install docker, it creates a user called docker. The command sudo usermod -aG docker ck modifies permissions of docker to those of the current user.

The script used is found in an official get-docker repository here

Step 2. Make Your Project Ready For Docker

Here is the project structure again:

.
├── .github
│   └── deploy.yaml
├── APP1
├── APP2
├── APP3
├── THE_USUAL_DJANGO_COMMON_FILES
├── Caddyfile
├── Dockerfile
├── docker-compose.yaml
├── manage.py
├── media
├── postgres
│   ├── Dockerfile
│   └── init
├── Procfile
├── README.md
├── requirements.txt
└── staticfiles

As you can see, we have 3 django apps, the usual stuff and then, there is Caddyfile, top Dockerfile, docker-compose.yaml, and a postgres directory with an init folder and its Dockerfile. There is also a .github directory with a deploy.yaml. These are the only foreign files you must have in your django project.

If you were using SQLite, you’d have a db directory with your sqlite file same way you have media and staticfiles directories.

The following is the content of each file required for docker deployment:

The Root Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Dockerfile

FROM python:3.8

RUN mkdir /PROJECT_NAME
WORKDIR /PROJECT_NAME

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

The CaddyFile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
yourdomain {
  bind {$ADDRESS}
  proxy / web:8000
  tls your_email
}

yourdomain/static/ {
  root /PROJECT_NAME/staticfiles/
  tls your_email
}

yourdomain/media/ {
  root /PROJECT_NAME/media/
  tls your_email
}

The Docker-compose.yaml File

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# docker-compose.yaml

version: '3'
services:

  web:
      build: .
      depends_on:
        - postgres
      container_name: PROJECT_NAME
      volumes:
      - .:/PROJECT_NAME
      - static:/PROJECT_NAME/staticfiles
      - media:/PROJECT_NAME/media
      expose:
        - 8000
      command: bash -c "python manage.py collectstatic --no-input && python manage.py makemigrations && python manage.py migrate && gunicorn --workers=3 PROJECT_NAME.wsgi -b 0.0.0.0:8000"

  postgres:
      build: ./postgres
      restart: unless-stopped
      expose:
        - "5432"
      environment:   # will be used by the init script
        LC_ALL: C.UTF-8
        POSTGRES_USER: user_name
        POSTGRES_PASSWORD: password
        POSTGRES_DB: your_database
      volumes:
        - pgdata:/var/lib/postgresql/data/  

  caddy:
    image: abiosoft/caddy
    depends_on:
    - "web"
    restart: always
    environment:
      ACME_AGREE: "true"
    ports:
    - "80:80"
    - "443:443"
    volumes:
    - ./Caddyfile:/etc/Caddyfile
    - caddy_certs:/root/.caddy
    - media:/PROJECT_NAME/media
    - static:/PROJECT_NAME/staticfiles

volumes:
  pgdata:
  media:
  static:
  caddy_certs:

Postgres Dockerfile and init

1
2
3
4
5
# postgres/Dockerfile

FROM postgres:latest

COPY ./init/01-db_setup.sh /docker-entrypoint-initdb.d/01-db-setup.sh
1
2
3
4
5
# postgres/init/01-db_setup.sh

psql -U postgres -c "CREATE USER user_name PASSWORD 'password'"
psql -U postgres -c "CREATE DATABASE your_database OWNER user_name"
psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE your_database TO user_name"

Make sure you cd into the init directory inside postgress folder and run chmod +x 01-db_setup.sh to make the file executable.

The Deploy.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# .github/deploy.yaml

name: Deploy

on: [push]

jobs:
  deploy:
    if: github.ref == 'refs/heads/master'
    runs-on: [ubuntu-latest]
    steps:
      - uses: actions/checkout@v1
      - name: Push to server
        uses: appleboy/ssh-action@master
        with:
          host:  YOUR_SERVER_IP
          username: USER_NAME
          password: PASSWORD
          script: |
            cd YOUR_PROJECT
            git pull
            docker-compose down
            docker-compose up -d

If you have added all the above files, your project is ready for deployment.

Now push to github.

Step 3. Clone Your Git Repository and Run Docker. I Use Github

As a pre-requisite, ssh to your server and run the command ssh-keygen and press enter all through. Don’t enter any password. How to SSH into a Server

Then, open a new terminal window on your computer and run the following command:

scp USER_NAME@YOUR_SERVER_IP:~/.ssh/id_rsa.pub temp_key.pub

How to SSH into a Server

The command will copy the public key of your newly created ssh key from the server to the temp_key.pub file in your current directory. And if you are using a text editor like VS Code, you can type code temp_key.pub to open it. Just use any text editor you got.

It will look something like:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDHBFwTkw2POX9Ecn4VCSCrdexnomnwEbrK0ToRobeQI5fsoF7NrlRG6AFPSOyKxbbzjc0j6+R4WgMIBIWzo+97yEUdbGM7mR7+g9P/3/lX8hVZHyhphWv+Mz/C0eok+j7SipThXKlLUfn4NqC5PxV0LwkEDt16/b8f30r+TvcuwQ4Xr+rNkoza0E46owl7ob5ZVxnT6btpxeyUbAw80kNFptxJg24eo4iHyKlSX2M7uMFWxXyHysOukBBAHYn+ux5LcGrFcRfbeREeG5QAyoiPOcPZc+F7/7GmgU5HzmJaa9NxqQ8dBthbLfEXHaAPDFnkLPR8ADvfBYuLZr2T6k7RXdY1iZlGuLlMqLqJ0ab26rQOg5GaTcE8r/o8PVooFtvSK86mXwDpUVDw9OuVanU5dfzNm/An0G8HNSAHeI3axkuE3Vg2XaeRIpz6wHlP6OBDBJJ6FfkagLzPVZ5mPhKk/Fo0xII+/ryw3hEkMApa6XiSL4zEdRZV09Fc6FAvrIs= ck@ubuntu-1cpu-1gb-uk-lon1

Copy the content of your key and go to your git hosting provider and add the content to your list of ssh keys. Name it anything. If your git provider is Github, click on your profile head on the upper right corner > settings > SSH and GPG Keys > Add new.

Now that you have your Git hosting ready to accept ssh from the server, you can go back to the server terminal and clone the repository. Remember, we are using the server as the new user you created above, never as root.

cd into the cloned project and run docker-compose up. Running this command the first time will take a few moments, however, subsequent runs will be snappy.

In production, you will always run docker-compose up -d, but in this case, we first want to see the output on the console so we can make sure things are running smoothly. In case you see an error, go back to the files we added and go through once again to make sure everything is correct.

If everything is running as expected, shut down the containers by using Ctrl + C. Then run docker-compose up -d and go have fun. Or sleep. I chose to sleep.

References

  1. https://lewiskori.com/blog/deploying-a-python-django-app-using-docker/

Leave a comment or share some love below.


comments powered by Disqus

You might also like