<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rojohasina Thierry RAFIDINORO</title>
    <description>The latest articles on DEV Community by Rojohasina Thierry RAFIDINORO (@thierry-django).</description>
    <link>https://dev.to/thierry-django</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3061683%2F5b9c3733-eb6d-413d-8b70-4efcb1c09ef7.png</url>
      <title>DEV Community: Rojohasina Thierry RAFIDINORO</title>
      <link>https://dev.to/thierry-django</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thierry-django"/>
    <language>en</language>
    <item>
      <title>Deploy Your Django App in Production — A Step-by-Step Guide with Docker &amp; PostgreSQL</title>
      <dc:creator>Rojohasina Thierry RAFIDINORO</dc:creator>
      <pubDate>Tue, 22 Apr 2025 14:15:47 +0000</pubDate>
      <link>https://dev.to/thierry-django/how-to-deploy-a-django-app-on-digitaloceans-app-platform-with-docker-3b6i</link>
      <guid>https://dev.to/thierry-django/how-to-deploy-a-django-app-on-digitaloceans-app-platform-with-docker-3b6i</guid>
      <description>&lt;p&gt;This tutorial walks you through deploying a Django app using Docker on DigitalOcean’s App Platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Objectives
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Set up a basic Django project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dockerize the app&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure a PostgreSQL database with Docker&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prepare the app for production&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy to DigitalOcean App Platform using Docker&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Python installed (preferably managed with pyenv)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Git installed and a GitHub account&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker and Docker Compose installed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A DigitalOcean account&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1 - Create the Project Locally
&lt;/h2&gt;

&lt;p&gt;Set your Python version (using &lt;a href="https://github.com/pyenv/pyenv" rel="noopener noreferrer"&gt;pyenv&lt;/a&gt;) and create a virtual environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pyenv local 3.13.3
python -m venv .venv
source .venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install Django and start your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install Django==5.2
django-admin startproject project .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the development server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python manage.py runserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit &lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt; in your browser. You should see the default Django welcome page.&lt;/p&gt;

&lt;h3&gt;
  
  
  First Git Commit
&lt;/h3&gt;

&lt;p&gt;Stop the server (Ctrl+C) and initialize a Git repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a .gitignore file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following to .gitignore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.venv/
__pycache__/
db.sqlite3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "Initial commit"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Hello World Page
&lt;/h3&gt;

&lt;p&gt;Start a new Django app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python manage.py startapp my_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  1. Add the app to INSTALLED_APPS in project/settings.py:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSTALLED_APPS = [
    ...,
    'my_app.apps.MyAppConfig',  # new
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Update project/urls.py to include your app's URLs:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.contrib import admin
from django.urls import include, path  # new

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('my_app.urls')),  # new
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Create a "Hello, world" view in my_app/views.py:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.http import HttpResponse


def hello_world(request):
    return HttpResponse("Hello, world")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Set up URLs for your app in my_app/urls.py:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.urls import path

from . import views

urlpatterns = [
    path('', views.hello_world, name='hello_world'),
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the server again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python manage.py runserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit &lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt; — you should now see your "Hello, world" message.&lt;/p&gt;

&lt;h4&gt;
  
  
  Final commit:
&lt;/h4&gt;

&lt;p&gt;Stop the server (Ctrl+C) and commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "Added hello world page"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2 - Dockerize the Application
&lt;/h2&gt;

&lt;p&gt;Let’s containerize the Django app using Docker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate requirements.txt
&lt;/h3&gt;

&lt;p&gt;Run the following command to capture your project dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip freeze &amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a Dockerfile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch Dockerfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM python:3.13.3-alpine

# Set work directory
WORKDIR /usr/src/app

# Prevent Python from writing .pyc files to disc and enable stdout/stderr logging
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# Install dependencies
RUN pip install --upgrade pip
COPY requirements.txt .
RUN pip install -r requirements.txt

# Copy project files
COPY . .

# Start Django server
CMD [ "python", "manage.py", "runserver", "0.0.0.0:8000" ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build the Docker Image
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build . -t tuto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run the Container
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -p 8000:8000 tuto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit &lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt; in your browser — your app should be up and running inside a container!&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a .dockerignore File
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch .dockerignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the following into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.venv/
__pycache__/
db.sqlite3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents unnecessary files from being copied into your Docker image.&lt;/p&gt;

&lt;h3&gt;
  
  
  Commit Your Work
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "Added Dockerfile"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use Docker Compose
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Why?
&lt;/h4&gt;

&lt;p&gt;Docker Compose lets you define your app’s setup in one file — services, ports, volumes, and more. It simplifies commands and makes starting your app as easy as &lt;code&gt;docker compose up&lt;/code&gt;. Ideal for development and collaboration.&lt;/p&gt;

&lt;p&gt;Create a Docker Compose file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  web:
    build: .
    volumes:
      - .:/usr/src/app/
    ports:
      - 8000:8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run your app using Docker Compose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit &lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt; again to confirm it's working.&lt;/p&gt;

&lt;p&gt;Stop the app (Ctrl+C), then commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "Added Docker Compose"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3 - Add a Database (PostgreSQL)
&lt;/h2&gt;

&lt;p&gt;Let’s move away from SQLite and connect the Django app to a PostgreSQL database using Docker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Dependencies
&lt;/h3&gt;

&lt;p&gt;Install PostgreSQL adapter and environment-based config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install psycopg2-binary==2.9.10 dj-database-url==2.3.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then update your requirements.txt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip freeze &amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update Django Settings
&lt;/h3&gt;

&lt;p&gt;In project/settings.py, update the DATABASES setting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import os
import dj_database_url  # make sure this is at the top with other imports

DATABASES = {
    'default': dj_database_url.parse(os.environ.get("DATABASE_URL")),
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells Django to read your database connection string from an environment variable called DATABASE_URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update compose.yml
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  web:
    build: .
    volumes:
      - .:/usr/src/app/
    ports:
      - 8000:8000
    env_file:
      - ./.env.docker
    depends_on:
      - db
  db:
    image: postgres:17.4-alpine
    volumes:
     - postgres_data:/var/lib/postgresql/data/
    env_file:
      - .env.db
volumes:
  postgres_data:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What’s happening here?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;web is your Django app container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;db is a PostgreSQL container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;env_file loads environment variables for each service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;volumes keeps your database persistent even if the container is restarted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create Environment Files
&lt;/h3&gt;

&lt;p&gt;.env.db (PostgreSQL config)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch .env.db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POSTGRES_USER=postgres
POSTGRES_PASSWORD=password
POSTGRES_DB=tuto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;.env.docker (Django config)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch .env.docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL=postgresql://postgres:password@db:5432/tuto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The db in the URL (&lt;a class="mentioned-user" href="https://dev.to/db"&gt;@db&lt;/a&gt;:5432) refers to the name of the service defined in compose.yml, not a hostname. Docker Compose makes this link automatically.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Ignore Environment Files
&lt;/h3&gt;

&lt;p&gt;Update both .gitignore and .dockerignore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.venv/
__pycache__/
db.sqlite3
.env.db
.env.docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run the project
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up --build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The --build flag forces the rebuilding of images before starting the containers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Visit &lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt; — your app should still work.&lt;/p&gt;

&lt;p&gt;However, you'll see a warning in the terminal:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have 18 unapplied migration(s).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Apply the Migrations
&lt;/h3&gt;

&lt;p&gt;To fix this, open a new terminal (leave the first one running), then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose exec web sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the container shell, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python manage.py migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then exit the shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, return to the first terminal, stop the containers (Ctrl+C), and restart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The migration warning should be gone!&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Commit
&lt;/h3&gt;

&lt;p&gt;Stop the containers (Ctrl+C) and commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "Uses a PostgreSQL database"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4 - Prepare for Deployment
&lt;/h2&gt;

&lt;p&gt;Let’s prepare the Django project for a real-world production environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set Up Environment Variables
&lt;/h3&gt;

&lt;p&gt;Update your settings.py to pull critical values from environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SECRET_KEY = os.environ.get("SECRET_KEY")
DEBUG = os.environ.get("DEBUG", "0") in ["1", 1, "True", "true"]
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(",")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update your .env.docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL=postgresql://postgres:password@db:5432/tuto
DEBUG=1
SECRET_KEY=FfAW8SOkA2_E_ZqE4z5yhuPvZMqpMYYt9UiwURoRqXQ
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a .env.example file to share the variable structure without exposing secrets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch .env.example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following to .env.example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL=postgresql://user:password@db:5432/db_name
DEBUG=0
SECRET_KEY=your-secret-key
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure Static Files with Whitenoise
&lt;/h3&gt;

&lt;p&gt;Install Whitenoise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install whitenoise==6.9.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update settings.py:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSTALLED_APPS = [
    ...
    'whitenoise.runserver_nostatic',  # new
    'django.contrib.staticfiles',
    ...
]
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',  # should be placed directly after the Django SecurityMiddleware
    ...
]
STATIC_ROOT = BASE_DIR / "staticfiles"  # new
STORAGES = {  # new
    "staticfiles": {
        "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
    },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an empty static directory so Git will track it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir static &amp;amp;&amp;amp; touch static/.keep
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add Gunicorn for Production
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Why?
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;runserver&lt;/code&gt; is for development only. Gunicorn is a production-ready server that handles multiple requests efficiently and keeps your Django app stable and responsive in real-world use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install gunicorn==23.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update your requirements.txt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip freeze &amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update the Dockerfile
&lt;/h3&gt;

&lt;p&gt;Let’s use a multi-stage build for development and production:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h4&gt;
  
  
  Why use a multi-stage build?
&lt;/h4&gt;

&lt;p&gt;A multi-stage Docker build lets us separate development and production setups in one Dockerfile. This keeps the production image clean and optimized, while still allowing flexibility for local development.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM python:3.13.3-alpine AS base

# Set work directory
WORKDIR /usr/src/app

# Prevent Python from writing .pyc files to disc and enable stdout/stderr logging
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# Install dependencies
RUN pip install --upgrade pip
COPY requirements.txt .
RUN pip install -r requirements.txt

# Copy project files
COPY . .

# Development stage
FROM base AS development
CMD [ "python", "manage.py", "runserver", "0.0.0.0:8000" ]

# Production stage
FROM base AS production
RUN chmod +x /usr/src/app/entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
CMD [ "gunicorn", "project.wsgi:application", "--bind", "0.0.0.0:8000" ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add entrypoint.sh
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch entrypoint.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste this content into entrypoint.sh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/sh

python manage.py migrate --noinput
python manage.py collectstatic --noinput

exec "$@"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script runs database migrations and collects static files automatically on deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update compose.yml for Local Development
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  web:
    build:
      target: development  # this chooses the "development" stage of the Dockerfile
    volumes:
      - .:/usr/src/app/
    ports:
      - 8000:8000
    env_file:
      - ./.env.docker
    depends_on:
      - db
  db:
    image: postgres:17.4-alpine
    volumes:
     - postgres_data:/var/lib/postgresql/data/
    env_file:
      - .env.db
volumes:
  postgres_data:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: The compose.yml file is only used for local development.&lt;br&gt;
In production (on DigitalOcean App Platform), only the final stage of the Dockerfile (the production stage) will be used.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Final Touches
&lt;/h3&gt;

&lt;p&gt;Commit your changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "prepared for deployment"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then push everything to GitHub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git remote add origin https://github.com/your-username/your-repo.git
git branch -M main
git push -u origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your project is now production-ready and hosted on GitHub!&lt;br&gt;
Next step: we’ll deploy it to DigitalOcean App Platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 – Deploy to DigitalOcean’s App Platform
&lt;/h2&gt;

&lt;p&gt;Now that your Django app is production-ready, let’s deploy it to the DigitalOcean App Platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Your App on DigitalOcean
&lt;/h3&gt;

&lt;p&gt;Go to &lt;a href="https://cloud.digitalocean.com/projects" rel="noopener noreferrer"&gt;https://cloud.digitalocean.com/projects&lt;/a&gt; and create an account if you don't already have one.&lt;/p&gt;

&lt;p&gt;Click on "Create", then "App Platform".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2k17af67s7v98lpa8yq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2k17af67s7v98lpa8yq.png" alt=" " width="260" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose “GitHub Repository” as the deployment source.&lt;/p&gt;

&lt;p&gt;Connect your GitHub account and select your repository + branch.&lt;/p&gt;

&lt;p&gt;Check Autodeploy to redeploy the app automatically when you push.&lt;/p&gt;

&lt;p&gt;Click Next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsru811qpyijbade3e7h7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsru811qpyijbade3e7h7.png" alt=" " width="604" height="862"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Select the Docker Build
&lt;/h3&gt;

&lt;p&gt;On the next screen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You’ll see two detected components: one for Python, one for Docker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete the one with “Python build detected”.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep only the “Docker build detected” — this uses your Dockerfile.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnoukp2lz0w995u1metj9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnoukp2lz0w995u1metj9.png" alt=" " width="642" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1jhdv4qeyymymi9b3xq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1jhdv4qeyymymi9b3xq1.png" alt=" " width="642" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure the Web Service
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Set the Public HTTP Port to 8000 — it must match the port defined in your Dockerfile.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj2gw3lcu9bsn7o4alspp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj2gw3lcu9bsn7o4alspp.png" alt=" " width="606" height="683"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the following app-level environment variables (based on .env.example):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DEBUG=0
SECRET_KEY=generate-a-secret-key
DATABASE_URL=${db.DATABASE_URL}
DJANGO_ALLOWED_HOSTS=${APP_DOMAIN}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Notes: Set DEBUG=0 in production.&lt;br&gt;
Generate a secure SECRET_KEY using: &lt;code&gt;python -c "import secrets; print(secrets.token_urlsafe())"&lt;/code&gt;&lt;br&gt;
${db.DATABASE_URL} will automatically point to your database once you create it (next step).&lt;br&gt;
${APP_DOMAIN} is a built-in variable that represents your app’s domain (e.g., yourapp.ondigitalocean.app).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3u4v007o8ihk5rj8cye.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3u4v007o8ihk5rj8cye.png" alt=" " width="606" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose any region, app name, and project as you want.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Far4wzgkrvbwbhvp2zxde.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Far4wzgkrvbwbhvp2zxde.png" alt=" " width="626" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on "Create app"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn8g0gplsc4bpmo3kdrt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn8g0gplsc4bpmo3kdrt.png" alt=" " width="409" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a PostgreSQL Database
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;h4&gt;
  
  
  Why use a managed PostgreSQL database?
&lt;/h4&gt;

&lt;p&gt;It’s more reliable and secure than running it in a container. DigitalOcean handles backups, scaling, and maintenance for you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Click on "Add resources", then "Create or attach database"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0xta2s60byprpv8r389.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0xta2s60byprpv8r389.png" alt=" " width="303" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Leave the name as db (so ${db.DATABASE_URL} works).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on "Create Database" — App Platform will redeploy automatically.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjkbsfkvchzpa52iolxio.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjkbsfkvchzpa52iolxio.png" alt=" " width="702" height="802"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Check Your Live App
&lt;/h3&gt;

&lt;p&gt;Once the build finishes, click the "Live App" button — you should see your "Hello, world" page online!&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Superuser
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;From your App Dashboard, open the Console tab.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the following command:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python manage.py createsuperuser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Provide a username, email, and password.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwknjkur3rp9ag3hxywb9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwknjkur3rp9ag3hxywb9.png" alt=" " width="626" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix the CSRF Error
&lt;/h3&gt;

&lt;p&gt;When logging into /admin, you will get a CSRF error.&lt;/p&gt;

&lt;p&gt;Fix it by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding the following line in settings.py file:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CSRF_TRUSTED_ORIGINS = os.environ.get("CSRF_TRUSTED_ORIGINS").split(",")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Adding the variable to both .env.docker and .env.example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CSRF_TRUSTED_ORIGINS=http://localhost,http://127.0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;And in App Platform, update your app’s environment variables:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CSRF_TRUSTED_ORIGINS=https://${APP_DOMAIN}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Commit and Push
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "Get CSRF_TRUSTED_ORIGINS from an environment variable"
git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Wait until the deployment is complete, visit /admin, log in with the superuser credentials, and you should be in!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Congratulations, your app has been successfully deployed!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You’ve built, containerized, and deployed a Django app with PostgreSQL on DigitalOcean’s App Platform. You now have a solid, production-ready setup — well done!&lt;/p&gt;

&lt;p&gt;Thanks for reading! 😊&lt;br&gt;
I’m Thierry, a freelance Django developer. I share tutorials and dev tips on &lt;a href="https://www.linkedin.com/in/rojohasina-thierry-rafidinoro/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; — feel free to connect or drop me a message if you have questions.&lt;/p&gt;

&lt;p&gt;👉 Check out the complete code here: &lt;a href="https://github.com/Rojohasina-R/digital-ocean-deployment-tutorial" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>docker</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
