Skip to main content

Deploy Django on GCP

How to deploy Django to Google Cloud Platform in VM instance

Google Cloud Platform (GCP) is Google's cloud computing solution that offers a variety of services to meet different purposes. Its primary features include global data centers, high security, and easy integration with other Google services.

GCP offers a wide range of services. For this tutorial, we will focus on Computer Engine that enables you to create and run virtual machines on Google Cloud Platform.


GCP Account Creation

Google Cloud Platform (GCP) account is integrated with your Google account. If you have had a Google account, you don't need to create another account for GCP.

Navigate to https://console.cloud.google.com/ to open Google Console. Create a project to start using GCP, you can also use existing project if you have one.


GCP Account Settings

Compute Engine is a service that allows you to create and run virtual machines (VMs) in the cloud. To enable this service, you need to set up billing account. If you are new to GCP, you can get some free credits using Free Trial.

Follow these steps to set up your trial account:

  • Navigate to GCP homepage at https://cloud.google.com/.
  • Click on the "Start a free trial" or "Start free" button.
  • GCP will offer $300 credit for free for the next 90 days.
  • Fill in the form then click "Continue".
  • Set up your payment method, You won't be charged after free trial ends unless you manually upgrade to paid account or exceed the free credit.
  • Click "Start my free trial" to complete the process.

GCP Creating a VM

A virtual machine (VM) is like a pretend computer that runs inside your real computer. It allows you use different operating systems and programs without changing your main computer configuration.

To create a virtual machine in GCP, follow these steps:

  • Sign in to your GCP console and click on the "Compute Engine" tab from the sidebar menu. If it isn't shown in the sidebar, you can search for it using the search bar at the top.
  • Click on "Create Instance" button.
  • Set the name of your VM, choose the region and zone that are near your location. It's important to select a region and zone that is closer to your location to ensure faster performance.
  • Choose "Machine type" that suits your budget.
  • Select the operating system you want to use in the "Boot disk" section. For this tutorial, we will use Ubuntu 22.04 LTS.
  • Allow the HTTP and HTTPS traffic in the "Firewall" section.
  • Leave the rest of the options as they are and click the "Create" button to start creating your virtual machine.
  • You will be redirected to Instances page. Wait until the instance is running.

Once your virtual machine is running, you can access it by clicking the "SSH" button in "Connect" column. The Ubuntu command will be used in the next steps since this instance is running on Ubuntu. If you are using a different operating system, adjust the command according to your OS.


The project to be deployed

Source project: https://github.com/app-generator/deploy-gcp-django

If git isn't installed, run following command to install it.

sudo apt-get install git

Then clone the project by running this command.

git clone https://github.com/app-generator/deploy-gcp-django

GCP Database set up

You only need to choose one of these databases, either PostgreSQL or MySQL.


👉 PostgreSQL

Install PostgreSQL in your instance

sudo apt-get install postgresql

Start the service

Once the installation is complete, PostgreSQL will be automatically running. Otherwise, use the following command to start the service.

sudo systemctl start postgresql

Login to PostgreSQL

sudo -u postgres psql

Create a Database

CREATE DATABASE appseed_db;

Replace appseed_db with the name that you want.

Create a user and grant permission to the user.

For this demo, we'll grant all permissions to all tables for the created user.

CREATE USER appseed_db_usr WITH PASSWORD 'pass';
GRANT ALL PRIVILEGES ON DATABASE appseed_db TO appseed_db_usr;

Replace appseed_db with your database name, appseed_db_usr and pass with your desired username and password.

Exit PostgreSQL

\q

👉 MySQL

  • Install MySQL in your instance
sudo apt-get install mysql-server libmysqlclient-dev
  • Start the service

Once the installation is complete, MySQL will be automatically running. Otherwise, use the following command to start the service.

sudo systemctl start mysql
  • Login to MySQL
sudo mysql
  • Create database
CREATE DATABASE appseed_db;

Replace appseed_db with the name that you want.

  • Create user and grant permission to the user.

For this demo, we'll grant all permissions to all tables for the created user.

CREATE USER 'appseed_db_usr'@'localhost' IDENTIFIED BY 'pass';
GRANT ALL PRIVILEGES ON appseed_db.* TO 'appseed_db_usr'@'localhost';
FLUSH PRIVILEGES;

Replace appseed_db with your database name, appseed_db_usr and pass with your desired username and password.

  • Exit MySQL
exit

GCP Environment set up

We need to set up the instance for Python environment. To find the right version to use, you need to check the Django version. If the version is not set in requirements.txt, it means the latest version. In Django documentation, we can found the compatible Python version.

Django 4.2 supports Python 3.8, 3.9, 3.10, and 3.11.


👉 Setting up Python

First, we need to install Python, pip, and virtualenv if they aren't already installed. Use the following commands to install them.

sudo apt-get update
sudo apt-get install python3 python3-pip python3-virtualenv

Verify the installation with the following command.

python3 --version
pip --version

👉 Setting up VENV and Dependencies

Enter the project directory, create a virtual environment to isolate the project dependencies, and activate it using the following commands.

cd deploy-gcp-django
virtualenv env
source env/bin/activate

Now you can install packages or dependencies without affecting other projects.

For installing the dependencies, you need to follow these steps:

  • Open requirements.txt file using a text editor, such as nano or vim.

  • Uncomment the package following the database you used by deleting the # in front of it.

    • psycopg2-binary: for PostgreSQL
    • mysqlclient: for MySQL
  • Save and exit, then install the packages.

pip install -r requirements.txt

👉 Setting up ENV Variables

Before moving on to the next steps, we need to set up environment variables so that the app can connect to the database and complete the setup.

  • Copy the env.sample file to .env.
cp env.sample .env
  • Open .env file using a text editor, such as nano or vim.

  • Remove comment from database variables and fill it by following your database configuration.

For PostgreSQL:

DB_ENGINE=postgresql
DB_PORT=5432

For MySQL:

DB_ENGINE=mysql
DB_PORT=3306
  • Fill out the other variables as needed, then save the file.

👉 Setting up the Database

Run the following commands to set up your database.

python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py createsuperuser

👉 Running the app

You're all set up! You can now run the app using the following command.

python3 manage.py runserver

Note that your project is currently only accessible locally.


GCP Domain settings

This demo use a domain that already been connected to Cloudflare.


👉 Adding DNS record in Cloudflare

First, we need to add a DNS record in Cloudflare to connect the domain to our GCP instance. Follow these steps:

  1. Add an A record.
  2. In the Name field, enter @ for the domain or anything else if you want to use a subdomain.
  3. In the IPv4 address field, enter the external IP of the instance. You can find this in GCP > VM Instances.
  4. Turn the Proxy status on.
  5. Click 'Save'.

👉 Setting up reverse proxy using NGINX

Next, we need to set up a reverse proxy to point the domain to our app.

Install NGINX in your instance.

sudo apt-get update
sudo apt-get install nginx

Start the NGINX service using the following command.

sudo systemctl start nginx

Set up a server block by creating a new configuration file

sudo nano /etc/nginx/sites-available/your_domain

Replace your_domain with your domain name.

Paste this following config into the file. Don't forget to replace your_domain with your domain name.

server {
listen 80;
listen [::]:80;

server_name your_domain;

location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

Enable the new config by creating a symbolic link to the site-enabled directory.

sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled

Remove the default config by unlinking it.

sudo unlink /etc/nginx/sites-enabled/default

Check your configuration by running this command.

sudo nginx -t

If there are no problems or errors, restart NGINX to apply the new config.

sudo systemctl restart nginx

Allowing access to your domain

Finally, we need to allow access to our domain in our Django settings. Follow these steps:

  1. Open the core/settings.py file in your project.

  2. Search ALLOWED_HOSTS and add your domain and external IP into it. For example:

ALLOWED_HOSTS = ['your_domain', 'external_IP']
  1. Save the file.

GCP SSL certificates

This demo will use SSL certificate from Cloudflare. You can also use certbot as an alternative.


👉 Creating an SSL certificate in Cloudflare

  1. Navigate to SSL/TLS > Origin Server in Cloudflare.
  2. Click on "Create Certificate".
  3. Keep the default config then click on "Create".
  4. You will have the Origin Certificate and Private Key. We will use this in the server.

👉 Editing the NGINX config

  1. Create a new file in /etc/ssl/certs, paste the Origin Certificate into it, and save.
sudo nano /etc/ssl/certs/cloudflare.pem
  1. Create a new file in /etc/ssl/private, paste the Private Key into it, and save.
sudo nano /etc/ssl/private/cloudflare.key
  1. Edit the NGINX config.
sudo nano /etc/nginx/sites-available/your_domain

Add this config below the existing config. Replace your_domain with your domain name.

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/ssl/certs/cloudflare.pem;
ssl_certificate_key /etc/ssl/private/cloudflare.pem;

server_name your_domain;

location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
  1. Check your configuration by running this command.

    sudo nginx -t
  2. If there are no problems, restart NGINX to apply this config.

    sudo systemctl restart nginx

👉 Changing the SSL/TLS encryption mode in Cloudflare

Finally, change the SSL/TLS encryption mode to Full (strict) in the Overview tab of the SSL/TLS section in the Cloudflare dashboard. This tells Cloudflare to always encrypt the communication between Cloudflare and the NGINX server at your source.


GCP CI/CD from Github

Continuous Integration and Continuous Deployment (CI/CD) is a process that automates the building, testing, and deployment of software. In this tutorial, we will set up CI/CD from Github to our GCP instance.


👉 Setting up SSH Keys and Secrets

Before creating Github Action, we need to set up the keys and secrets.

  1. Generate a new SSH key on your local computer.
ssh-keygen -t ed25519 -a 200 -C "your_email@example.com"
  1. Copy the public key, the default is located in ~/.ssh/id_ed25519.pub.
  2. Add it to the authorized keys in the server. Open ~/.ssh/authorized_keys and paste the public key below the existing keys.
  3. Open your repository on Github. Go to Settings > Secrets and variables > Actions.
  4. Click on "New repository secret" to add a secret. You need to add these following secrets:
    • HOST: external IP of instance
    • USERNAME: instance username
    • KEY: private key, from -----BEGIN until end of the key.
    • PORT: 22

👉 Setting up CI/CD with Github Action

After setting up the SSH keys and secrets, we can move the next steps:

  1. Create a new folder .github/workflows in the project.
  2. Create a new file cd.yml in the .github/workflows, paste this following code.
name: Django CI/CD Workflow

on:
push:
branches:
- main

jobs:
deployment:
runs-on: ubuntu-latest # according to your os
steps:
- name: executing remote ssh commands using ssh key
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
script: |
cd ~/deploy-gcp-django
git pull origin main
env/bin/pip install -r requirements.txt
env/bin/python manage.py migrate
  1. Save the file then commit and push it to the repository.

Now, every time you push code to the main branch on Github, it will automatically deploy to your GCP instance.


GCP LIVE Service monitoring

We'll use UptimeRobot to monitor the app. UptimeRobot is a popular online service that monitors the uptime and performance of websites, servers, and other online services.

Go to UptimeRobot create an account or sign in if you already have account. Create monitor by clicking "Add New Monitor" button then follow this config:

  • Monitor Type: HTTP(s)
  • Friendly Name: django-gcp (or anything else you want)
  • URL (or IP): your_domain

Keep the rest of the config as default and click "Create Monitor"

UptimeRobot will now start monitoring your app. You can view the monitor status and performance data on the UptimeRobot dashboard


✅ Resources