Deploying a Dockerized Django App to Render with GitHub Actions(CI-CD)

  • Home
  • Deploying A Dockerized Django App To Render With GitHub Actions(CI-CD)
Blog preview image

This guide explains how to deploy a Dockerized Django application to Render using GitHub Actions for CI/CD.

By the end, you will have:

  • Containerize a Django project with Docker
  • Use PostgreSQL and Redis in development
  • Run automated tests before deployment
  • Deploy automatically to Render after successful tests

1. Dockerizing the Django Application

The first step is to containerize the Django project using Docker.

Here is an example Dockerfile:

# Use the official Python runtime image
FROM python:3.13

# Create the app directory
RUN mkdir /app
WORKDIR /app

# Environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# Upgrade pip
RUN pip install --upgrade pip

# Copy dependencies
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt

# Copy the Django project
COPY . /app/

# Expose port
EXPOSE 8000

# Start server
CMD ["/bin/bash", "-c", "if [ \"$ENV_MODE\" = \"prod\" ]; then python manage.py collectstatic --noinput && python manage.py makemigrations && python manage.py migrate --noinput && gunicorn YOUR_APP_NAME.wsgi:application --bind 0.0.0.0:8000; else python manage.py runserver 0.0.0.0:8000; fi"]

Notice the ENV_MODE variable.

  • If it isprod, the app runs with Gunicorn.
  • Otherwise, it defaults to Django’s development server to run on localhost.

2. Adding PostgreSQL & Redis with Docker Compose

A typical Django setup also requires a database layer. Here is how PostgreSQL can be included in docker-compose.yml:

services:
db:
image: postgres:17
environment:
POSTGRES_DB: ${DATABASE_NAME}
POSTGRES_USER: ${DATABASE_USERNAME}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
env_file:
- .env

app:
build: .
volumes:
- .:/app
ports:
- "8000:8000"
depends_on:
- db
env_file:
- .env

volumes:
postgres_data:

All sensitive values (like DATABASE_PASSWORD and DJANGO_SECRET_KEY) should be placed in a .env file, not in version control.

3. Pushing the Project to GitHub

Once the app is Dockerized, it needs to be pushed to GitHub to set up CI/CD. Here’s the basic workflow:

git init
git add .
git commit -m "Initial commit"
git branch -M master
git remote add origin https://github.com/YOUR_USERNAME/YOUR_REPO.git
git push -u origin master

4. Setting Up GitHub Actions

GitHub Actions can be used to test the code and deploy it automatically.

Create a file in your project root directory:  .github/workflows/deploy.yaml

This workflow does two things:

  1. Test job → spins up PostgreSQL, installs dependencies, runs Django tests
  2. Deploy job → deploys to Render only if tests pass

Example workflow file:

name: CI/CD to Render

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_DB: ${{ secrets.DATABASE_NAME }}
POSTGRES_USER: ${{ secrets.DATABASE_USER }}
POSTGRES_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
env:
DATABASE_ENGINE: postgresql
DATABASE_NAME: ${{ secrets.DATABASE_NAME }}
DATABASE_USERNAME: ${{ secrets.DATABASE_USER }}
DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
DATABASE_HOST: localhost
DATABASE_PORT: 5432
DJANGO_SECRET_KEY: ${{ secrets.DJANGO_SECRET_KEY }}
DEBUG: True
ALLOWED_HOSTS: localhost
run: |
python manage.py makemigrations
python manage.py migrate --noinput
python manage.py test

deploy:
needs: test
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- name: Deploy to Render
uses: JorgeLNJunior/render-deploy@v1.4.5
with:
service_id: ${{ secrets.RENDER_SERVICE_ID }}
api_key: ${{ secrets.RENDER_API_KEY }}
wait_deploy: true
clear_cache: false

Sensitive values (RENDER_API_KEYRENDER_SERVICE_ID, DB credentials) should be stored in GitHub Secrets, never hardcoded.

5. Configuring Render

  1. Sign up at Render.
  2. Create a New Web Service → choose Docker.
  3. Connect your GitHub repository.
  4. Specify the Dockerfile path.
  5. Add environment variables such as:
  • ENV_MODE=prod
  • DJANGO_SECRET_KEY=your_secret_key
  • DATABASE_URL=postgres://...

6. Linking GitHub Actions to Render

  1. In Render → Service Settings, copy the Service ID and API Key.
  2. In GitHub → Settings → Secrets and Variables → Actions, add:
  • RENDER_SERVICE_ID=xxxxxx
  • RENDER_API_KEY=xxxxxx
  • DATABASE_NAME → database name for GitHub Actions
  • DATABASE_USER → database user for GitHub Actions
  • DATABASE_PASSWORD → database password for GitHub Actions
  • DJANGO_SECRET_KEY → Django secret key for testing in CI

Now, whenever code is pushed to master:

  1. Tests run in GitHub Actions
  2. If tests pass → the app will be deployed automatically to Render 🎉

If this guide helped you, don’t forget to give it a clap 👏 and share it with other Django developers. Follow me for more hands-on deployment and backend tips!

Written by Anthony Shoshi Gomes

Anthony, a passionate software engineer, loves coding, innovating, and learning.
I share findings, value feedback, and connect to inspire progress.

Subscribe

Subscribe to our newsletter, stay updated with us

Enter your e-mail to get the latest news.

Quick Question?