Skip to content

Raguggg/django-postgresql-cron-nginx-docker-compose

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🚀 Deploying Django with PostgreSQL, Cron Jobs, and Nginx in Docker Compose with Static Files Serving

django docker

In this guide, we'll walk through how to deploy a Django application with PostgreSQL, Cron jobs, and Nginx in Docker containers. This setup provides a robust environment for scalable web applications with background task handling and efficient static file serving.

1. Why Use Docker for Django Deployment? 🐳

Docker offers several benefits when it comes to deploying applications, including:

  • Consistency: Your application will run the same in every environment, reducing the risk of "it works on my machine" issues. ✔️
  • Isolation: Each service (Django, PostgreSQL, Nginx) runs in its own container, making it easier to manage dependencies and configurations. 🔒
  • Scalability: Docker makes it easy to scale individual components like the database or web service based on your needs. 📈

2. Docker Compose: Defining Multiple Services 📝

To orchestrate multiple containers for Django, PostgreSQL, and Nginx, we use Docker Compose. It allows us to define and run multi-container Docker applications. By using a single docker-compose.yml file, you can manage the configuration for all services in one place.

  • PostgreSQL: The database service uses the official PostgreSQL image. It is configured with environment variables like POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB for quick setup. The data is persisted in a volume (./pgdata:/var/lib/postgresql/data) to prevent data loss between container restarts.

  • Django Web Service: The Django application is built using a custom Dockerfile. It includes all necessary dependencies (including the cron service) and runs the Django app with Gunicorn for production-level performance.

  • Nginx: Nginx serves as a reverse proxy and static file server. It proxies requests to the Django app and serves static files like images, CSS, and JavaScript.

3. Setting Up PostgreSQL Database 🗄️

The PostgreSQL service uses a health check (pg_isready) to ensure that the database is fully initialized and ready to accept connections before any dependent services (like Django) start.

Additionally, an init.sql script can be added to initialize the database schema or perform other setup tasks, such as creating the main database if it doesn’t already exist. ⚙️

4. Django Setup with Cron Jobs 🕰️

Cron jobs are essential for running background tasks at scheduled times. In this setup:

  • Database Migrations: When the container starts, Django applies any database migrations to ensure that the schema is up to date. 🔄
  • Static Files Collection: Static files are collected into a single directory, making them easier to serve, especially when using a reverse proxy like Nginx. 📂
  • Superuser Creation: A Django superuser is automatically created using environment variables, so you don’t need to manually create one after deployment. 👤
  • Cron Jobs: Django’s built-in django-crontab is used to manage cron jobs within the container. When the service starts, it adds the necessary cron jobs to run tasks like sending emails or processing background tasks. 📧

5. Nginx as a Reverse Proxy 🔄

Nginx is configured to forward HTTP requests to the Django application, handling tasks like:

  • Load Balancing: Distributes traffic across multiple Django worker processes (or even multiple instances of the web service). ⚖️
  • Static File Serving: Nginx efficiently serves static files (CSS, JavaScript, images) directly, which improves performance. These files are served from a volume mounted at /static. 🖼️

With this setup, Nginx ensures that the Django web server handles dynamic requests (e.g., API calls), while static content is served directly by Nginx.

6. Environment Variables for Configuration 🌐

Environment variables play a crucial role in configuring the application and database. For instance, variables like DB_NAME, DB_USER, and DB_PASSWORD are used to configure the connection between Django and PostgreSQL.

Other environment variables include:

  • Superuser credentials (SUPER_USER_NAME, SUPER_USER_PASSWORD, etc.) for automatic creation of a Django admin user. 🔑
  • Database host and port to ensure that Django can connect to the PostgreSQL database running in a separate container. 🌍

7. Health Checks for Reliable Service Startup

Docker Compose includes a feature for defining health checks for each service. This ensures that the services (like PostgreSQL and Django) are only started once they are fully ready to handle requests:

  • PostgreSQL uses pg_isready to check the database's readiness. 🟢
  • Django uses an HTTP request (curl) to check if the admin panel is accessible. 🖥️

These checks ensure that services are only started when they are fully operational, reducing the chances of failures during startup.

8. Scaling with Docker 📊

One of the great advantages of Docker is the ability to scale your services horizontally. For example:

  • You can scale the web service (Django) by running multiple instances of the container behind the Nginx reverse proxy. This ensures that your application can handle more traffic without degradation in performance. 📈
  • Similarly, you can scale the database by running PostgreSQL in a replicated setup (though this requires further configuration). 🔁

9. Running the Application 🚀

Once everything is set up in your Docker containers, running the application is as simple as using the following command:

docker-compose up --build

This will:

  • Build the necessary Docker images. 🏗️
  • Start the containers for PostgreSQL, Django, and Nginx. 🖥️
  • Ensure that all services are linked and running as expected. ✅

10. Accessing the Application 🌍

Once the services are running, you can access your Django application through http://localhost:8000. The admin panel will be available at http://localhost:8000/admin. Or use IP address or domain name if deployed on a server. 🌐

For production environments, you should update the nginx.conf to reflect your domain and ensure SSL certificates are configured for secure connections. 🔒


Key Points to Consider 🧠

  1. DB:
    • Use init.sql to initialize the database schema to avoid manual setup. 🛠️
    • Use health checks to ensure the database is ready before starting dependent services. 🟢
    • Persist data in a volume to prevent data loss between container restarts. 💾
  2. Django:
    • Use a custom Dockerfile to build the Django application with all dependencies like cron jobs. 🛠️
    • Use environment variables for configuration (e.g., database connection, superuser credentials). 🗝️
    • Start cron services to manage background tasks ⏰
    • In code, create a .env file to store all the environment variables because Docker adds environment variables to the working directory only, but cron jobs run from the root directory in the container. Use python-dotenv to load environment variables from .env file. 🌍
    • Use django-crontab to manage cron jobs within the container. 🔄
    • I use health checks by running the curl command to check if the admin panel is accessible. 🖥️ In the lightweight Python image, curl is not included. Please install it to use the health check, otherwise, Nginx will not start.
  3. Nginx:
    • include mime.types; in nginx.conf to serve static files because by default, Nginx responds with content type text/plain, which browsers will not render. 🖼️

Conclusion 🎯

Using Docker for deploying Django with PostgreSQL, Cron jobs, and Nginx provides a powerful, scalable, and maintainable solution. By using Docker Compose, you can easily manage multiple services and configurations in a single environment. This setup also ensures that your application is production-ready, with the ability to scale, handle background tasks, and serve static files efficiently. ⚡