{"id":1807,"date":"2024-06-05T23:41:15","date_gmt":"2024-06-06T03:41:15","guid":{"rendered":"https:\/\/www.craigperler.com\/blog\/?p=1807"},"modified":"2024-06-07T10:17:04","modified_gmt":"2024-06-07T14:17:04","slug":"setup-django-docker-postgresql-react","status":"publish","type":"post","link":"https:\/\/www.craigperler.com\/blog\/2024\/06\/05\/setup-django-docker-postgresql-react\/","title":{"rendered":"How to Set up Django with Docker, PostgreSQL and React"},"content":{"rendered":"\n<p>Figuring out how to set up Django with Docker, PostgreSQL, and React can be a complex task, especially if you, like me, <a href=\"https:\/\/www.craigperler.com\/blog\/2017\/09\/25\/toddler-piano-lessons\/\">don&#8217;t really code much nowadays<\/a>. The boilerplate effort around configuring these technologies is often the first thing I forget with each re-immersion. This article serves as a reminder for how to kickstart a Python web project using Django, PostgreSQL, Docker, and React.<em> So you don&#8217;t have to figure it out each time you just want to build a simple website. <\/em>While tools like <a href=\"https:\/\/github.com\/cookiecutter\/cookiecutter-django\">cookiecutter-django<\/a> offer a solid alternative, there is something invaluable about the hands-on approach that truly cements how these pieces fit together.<\/p>\n\n\n\n<p>We\u2019ll take an iterative approach, introducing new components with each section. First, we\u2019ll set up a basic Django project using a virtual environment. We will then containerize the project with Docker, integrate PostgreSQL as a robust database solution, and finally, incorporate React to build a dynamic frontend. This step-by-step guide ensures a comprehensive understanding of how to set up Django with Docker, PostgreSQL, and React, creating a modern web application.<\/p>\n\n\n\n<h3 id=\"prerequisites\" class=\"wp-block-heading\"><strong>Prerequisites<\/strong><\/h3>\n\n\n\n<p>Before diving into setting up your Django project, make sure you have the following prerequisites in place:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Python<\/strong>: Ensure you have Python installed on your system. Download it from the <a href=\"https:\/\/www.python.org\/downloads\/\">official Python website<\/a>.<\/li>\n\n\n\n<li><strong>PyCharm (or another IDE)<\/strong>: We\u2019ll be using PyCharm in this tutorial, but you can use any other integrated development environment (IDE) of your choice.<\/li>\n\n\n\n<li><strong>Pipenv<\/strong>: This tool helps manage project dependencies and virtual environments. Install Pipenv by running:<\/li>\n<\/ol>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\npip install pipenv\n<\/pre><\/div>\n\n\n<h3 id=\"setting-up-the-project\" class=\"wp-block-heading\"><strong>Setting Up the Project<\/strong><\/h3>\n\n\n\n<p>With the prerequisites in place, let\u2019s start setting up our Django project.<\/p>\n\n\n\n<h2 id=\"set-up-django\" class=\"wp-block-heading\">Set up <strong>Django<\/strong><\/h2>\n\n\n\n<p>When starting a new Django project, the first step is to set up a solid foundation using a virtual environment. This isolates your project\u2019s dependencies, ensuring that packages required for one project don\u2019t interfere with others. We\u2019ll use Pipenv, a tool that combines package management and virtual environment handling, to streamline this process.<\/p>\n\n\n\n<h3 id=\"create-a-new-pycharm-project\" class=\"wp-block-heading\"><strong>Create a New PyCharm Project<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Name Your Project<\/strong>: Start by naming your project. This is the initial setup where you define your project\u2019s identity.<\/li>\n\n\n\n<li><strong>Select the Python Virtual Environment Tool<\/strong>: Choose Pipenv. This helps in managing dependencies and creating isolated environments.<\/li>\n\n\n\n<li><strong>Choose the Base Interpreter<\/strong>: Select the Python version you want to use for your project.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1160\" height=\"514\" src=\"https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.31.33%E2%80%AFPM.png?resize=1160%2C514&#038;ssl=1\" alt=\"Set up Django in PyCharm\" class=\"wp-image-1812\" srcset=\"https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.31.33%E2%80%AFPM.png?resize=1160%2C514&amp;ssl=1 1160w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.31.33%E2%80%AFPM.png?resize=800%2C355&amp;ssl=1 800w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.31.33%E2%80%AFPM.png?resize=1536%2C681&amp;ssl=1 1536w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.31.33%E2%80%AFPM.png?resize=120%2C53&amp;ssl=1 120w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.31.33%E2%80%AFPM.png?resize=90%2C40&amp;ssl=1 90w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.31.33%E2%80%AFPM.png?resize=320%2C142&amp;ssl=1 320w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.31.33%E2%80%AFPM.png?resize=560%2C248&amp;ssl=1 560w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.31.33%E2%80%AFPM.png?w=1584&amp;ssl=1 1584w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/figure>\n\n\n\n<h3 id=\"about-pipenv\" class=\"wp-block-heading\"><strong>About Pipenv<\/strong><\/h3>\n\n\n\n<p>Your project will include a base Pipfile, which contains all the packages needed to run the project. Pipenv is a powerful tool that combines the functionality of virtual environments with dependency management, making it easier to maintain consistent development environments.<\/p>\n\n\n\n<h3 id=\"install-django\" class=\"wp-block-heading\"><strong>Install Django<\/strong><\/h3>\n\n\n\n<p>With the virtual environment ready, the next step is to install Django. Open the terminal within PyCharm and run the following command:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\npipenv install django\n<\/pre><\/div>\n\n\n<p>This command installs Django within the virtual environment, ensuring that your project has access to the necessary libraries.<\/p>\n\n\n\n<h3 id=\"create-a-django-project\" class=\"wp-block-heading\"><strong>Create a Django Project<\/strong><\/h3>\n\n\n\n<p>Now, let\u2019s set up the initial structure of our Django project. Run these commands in the terminal:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndjango-admin startproject config .\n.\/manage.py migrate\n.\/manage.py runserver\n<\/pre><\/div>\n\n\n<p>By default, Django uses SQLite as the database backend. After running migrations, you\u2019ll see a db document in your project folder, indicating that the database is set up and ready to use. You can now access your locally running website at <a href=\"http:\/\/127.0.0.1:8000\/\">http:\/\/127.0.0.1:8000\/<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1160\" height=\"561\" src=\"https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.34.36%E2%80%AFPM.png?resize=1160%2C561&#038;ssl=1\" alt=\"Shows a successfully running local Django website (not yet with Docker, PostgreSQL, React).\" class=\"wp-image-1813\" srcset=\"https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.34.36%E2%80%AFPM.png?resize=1160%2C561&amp;ssl=1 1160w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.34.36%E2%80%AFPM.png?resize=800%2C387&amp;ssl=1 800w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.34.36%E2%80%AFPM.png?resize=1536%2C742&amp;ssl=1 1536w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.34.36%E2%80%AFPM.png?resize=120%2C58&amp;ssl=1 120w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.34.36%E2%80%AFPM.png?resize=90%2C44&amp;ssl=1 90w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.34.36%E2%80%AFPM.png?resize=320%2C155&amp;ssl=1 320w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.34.36%E2%80%AFPM.png?resize=560%2C271&amp;ssl=1 560w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.34.36%E2%80%AFPM.png?resize=1920%2C928&amp;ssl=1 1920w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-3.34.36%E2%80%AFPM.png?w=1982&amp;ssl=1 1982w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/figure>\n\n\n\n<p>Next, we\u2019re going to build on this project by using Docker, defining a container within which our project will deploy and run.<\/p>\n\n\n\n<h2 id=\"set-up-django-with-docker\" class=\"wp-block-heading\">Set up Django with Docker<\/h2>\n\n\n\n<p>While Pipenv is great for managing dependencies and virtual environments, Docker takes things a step further by providing complete isolation for your application, ensuring it runs consistently across different environments. Docker allows you to package your application with all its dependencies, including the operating system, into a single container. This is particularly useful for development, testing, and deployment, as it eliminates the \u201cit works on my machine\u201d problem.<\/p>\n\n\n\n<h3 id=\"install-docker\" class=\"wp-block-heading\"><strong>Install Docker<\/strong><\/h3>\n\n\n\n<p>First, we need to install Docker:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Download Docker<\/strong>: Get Docker from its <a href=\"https:\/\/www.docker.com\/\">official website<\/a>.<\/li>\n\n\n\n<li><strong>Follow the installation instructions<\/strong>: Install Docker based on your operating system.<\/li>\n\n\n\n<li><strong>Ensure Docker is running<\/strong>: Docker should be running as a background process on your computer.<\/li>\n<\/ol>\n\n\n\n<h3 id=\"create-a-dockerfile\" class=\"wp-block-heading\"><strong>Create a Dockerfile<\/strong><\/h3>\n\n\n\n<p>A Dockerfile is a script that contains a series of instructions on how to build a Docker image for your application. Create a file named <em>Dockerfile<\/em> at the root of your project with the following content:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n# Use the official Python image from the Docker Hub\nFROM python:3.11\n\n# Prevents Python from writing .pyc files to disk\nENV PYTHONDONTWRITEBYTECODE 1\n\n# Ensures that the output of the Python application is sent straight to the terminal\nENV PYTHONUNBUFFERED 1\n\n# Set the working directory inside the Docker container\nWORKDIR \/app\n\n# Install pipenv for managing dependencies and virtual environments\nRUN pip install pipenv\n\n# Ensure pipenv uses the specified Python version (Python 3.11) for the virtual environment\nRUN pipenv --python \/usr\/local\/bin\/python3.11\n\n# Copy the entire project directory to the working directory in the Docker container\nCOPY . \/app\n\n# Install pipenv and then use it to install the dependencies defined in the Pipfile\nRUN pipenv install --system --deploy\n<\/pre><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>FROM<\/strong>: Specifies the base image (Python 3.11) to use.<\/li>\n\n\n\n<li><strong>ENV PYTHONDONTWRITEBYTECODE<\/strong>: Prevents Python from writing .pyc files, keeping the container clean.<\/li>\n\n\n\n<li><strong>ENV PYTHONUNBUFFERED<\/strong>: Ensures all output is sent directly to the terminal.<\/li>\n\n\n\n<li><strong>WORKDIR<\/strong>: Sets the working directory inside the container to \/app.<\/li>\n\n\n\n<li><strong>COPY<\/strong>: Copies the current directory\u2019s content to the \/app directory inside the container.<\/li>\n\n\n\n<li><strong>RUN<\/strong>: Installs Pipenv and the dependencies listed in the Pipfile.<\/li>\n<\/ul>\n\n\n\n<h3 id=\"build-the-docker-image\" class=\"wp-block-heading\"><strong>Build the Docker Image<\/strong><\/h3>\n\n\n\n<p>To create the Docker image, run the following command from the root of your project:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker build .\n<\/pre><\/div>\n\n\n<h3 id=\"create-docker-compose-yml\" class=\"wp-block-heading\"><strong>Create docker-compose.yml<\/strong><\/h3>\n\n\n\n<p>Docker Compose allows you to define and run multi-container Docker applications. Create a file named <em>docker-compose.yml<\/em> at the root of your project with the following content:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\nversion: '3.8'\nservices:\n  web:\n    build: .\n    command: python manage.py runserver 0.0.0.0:8000\n    volumes:\n      - .:\/app\n    ports:\n      - &quot;8000:8000&quot;\n<\/pre><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>version<\/strong>: Specifies the version of the Docker Compose file format.<\/li>\n\n\n\n<li><strong>services<\/strong>: Defines the services that make up your application.<\/li>\n\n\n\n<li><strong>web<\/strong>:\n<ul class=\"wp-block-list\">\n<li><strong>build<\/strong>: Builds the Docker image using the Dockerfile in the current directory.<\/li>\n\n\n\n<li><strong>command<\/strong>: Runs the Django development server inside the container.<\/li>\n\n\n\n<li><strong>volumes<\/strong>: Mounts the current directory to the \/app directory inside the container, enabling live code reloading.<\/li>\n\n\n\n<li><strong>ports<\/strong>: Maps port 8000 on the container to port 8000 on the host machine.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 id=\"start-the-django-project-in-docker\" class=\"wp-block-heading\"><strong>Start the Django Project in Docker<\/strong><\/h3>\n\n\n\n<p>Finally, start the Docker container by running:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker-compose up\n<\/pre><\/div>\n\n\n<p>What we\u2019ve done here is define a Python-based Docker image for our project. We copy the project into that image, install the Python dependencies, and then start the development server inside the container. This setup ensures that your development environment is consistent and isolated, making it easier to manage dependencies and avoid conflicts.<\/p>\n\n\n\n<p>By using Docker, we\u2019ve created a consistent and reproducible environment for our Django project, ensuring it runs the same way on any system with Docker installed.<\/p>\n\n\n\n<h3 id=\"managing-docker-containers\" class=\"wp-block-heading\">Managing Docker Containers<\/h3>\n\n\n\n<p>Here are some essential Docker commands to manage your containers and images:<\/p>\n\n\n\n<h4 id=\"stopping-the-docker-container\" class=\"wp-block-heading\"><strong>Stopping the Docker Container<\/strong><\/h4>\n\n\n\n<p>To stop the Docker container, you can use:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker-compose down\n<\/pre><\/div>\n\n\n<p>This command stops and removes the containers defined in your docker-compose.yml file.<\/p>\n\n\n\n<h4 id=\"rebuilding-the-docker-image\" class=\"wp-block-heading\"><strong>Rebuilding the Docker Image<\/strong><\/h4>\n\n\n\n<p>You should rebuild the Docker image if you make changes to the Dockerfile or the dependencies listed in your Pipfile. To rebuild the image, run:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker-compose up --build\n<\/pre><\/div>\n\n\n<p>This command rebuilds the Docker image and starts the containers.<\/p>\n\n\n\n<h4 id=\"deleting-docker-containers-images-and-volumes\" class=\"wp-block-heading\"><strong>Deleting Docker Containers, Images, and Volumes<\/strong><\/h4>\n\n\n\n<p>To clean up Docker resources, you might need to remove containers, images, or volumes. Here are some useful commands:<\/p>\n\n\n\n<p><strong>Remov<\/strong>e a <strong>specific container<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker rm &lt;container_id&gt;\n<\/pre><\/div>\n\n\n<p>Removing <strong>a specific image<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker rmi &lt;image_id&gt;\n<\/pre><\/div>\n\n\n<p><strong>Or a specific volume<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker volume rm &lt;volume_name&gt;\n<\/pre><\/div>\n\n\n<p><strong>Pruning all stopped containers, dangling images, and unused networks<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker system prune\n<\/pre><\/div>\n\n\n<h2 id=\"set-up-django-with-docker-and-postgresql\" class=\"wp-block-heading\">Set up Django with Docker and PostgreSQL<\/h2>\n\n\n\n<p>To make your Django application production-ready, we need to add support for PostgreSQL, a robust and widely-used database system. Instead of installing PostgreSQL locally, we\u2019ll run it within a Docker container, maintaining our isolated and consistent development environment.<\/p>\n\n\n\n<h3 id=\"install-postgresql-drivers-in-docker\" class=\"wp-block-heading\"><strong>Install PostgreSQL Drivers in Docker<\/strong><\/h3>\n\n\n\n<p>To enable Django to communicate with PostgreSQL, we need to install the PostgreSQL drivers. With the Docker container up and running, execute the following:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker-compose exec web pipenv install psycopg2-binary\n<\/pre><\/div>\n\n\n<p>This installs psycopg2-binary, a PostgreSQL database adapter for Python, into the Docker container.<\/p>\n\n\n\n<h3 id=\"add-postgresql-support-to-the-docker-services\" class=\"wp-block-heading\"><strong>Add PostgreSQL Support<\/strong> to the Docker Services<\/h3>\n\n\n\n<p>Update docker-compose.yml to include a db service. Also, to ensure your PostgreSQL data persists even if the container is stopped or removed, update docker-compose.yml to include a volume for PostgreSQL data:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\nversion: '3.8'\nservices:\n  db:\n    image: postgres\n    environment:\n      - &quot;POSTGRES_HOST_AUTH_METHOD=trust&quot;\n    volumes:\n      - postgres_data:\/var\/lib\/postgresql\/data\n  web:\n    build: .\n    command: python manage.py runserver 0.0.0.0:8000\n    volumes:\n      - .:\/app\n    ports:\n      - &quot;8000:8000&quot;\n    depends_on:\n      - db\nvolumes:\n  postgres_data:\n<\/pre><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>db<\/strong>: Defines the PostgreSQL service using the official PostgreSQL image.<\/li>\n\n\n\n<li><strong>environment<\/strong>: Sets the POSTGRES_HOST_AUTH_METHOD to trust for simplicity.<\/li>\n\n\n\n<li><strong>depends_on<\/strong>: Ensures the web service waits for the db service to start.<\/li>\n\n\n\n<li><strong>volumes<\/strong>: Mounts a volume named postgres_data to persist data in \/var\/lib\/postgresql\/data inside the container.<\/li>\n<\/ul>\n\n\n\n<h3 id=\"update-django-settings-for-postgresql\" class=\"wp-block-heading\"><strong>Update Django Settings for PostgreSQL<\/strong><\/h3>\n\n\n\n<p>Next, configure Django to use PostgreSQL. In config\/settings.py, update the DATABASES setting:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nDATABASES = {\n    'default': {\n        'ENGINE': 'django.db.backends.postgresql',\n        'NAME': 'postgres',\n        'USER': 'postgres',\n        'PASSWORD': 'postgres',\n        'HOST': 'db',\n        'PORT': '5432',\n    }\n}\n<\/pre><\/div>\n\n\n<p>This configuration tells Django to connect to the PostgreSQL database running in the db container.<\/p>\n\n\n\n<h3 id=\"rebuild-and-start-docker-containers\" class=\"wp-block-heading\"><strong>Rebuild and Start Docker Containers<\/strong><\/h3>\n\n\n\n<p>After making these changes, we need to rebuild the Docker image and restart the containers:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker-compose down\ndocker-compose up --build\n<\/pre><\/div>\n\n\n<h3 id=\"run-django-migrations-and-create-superuser\" class=\"wp-block-heading\"><strong>Run Django Migrations and Create Superuser<\/strong><\/h3>\n\n\n\n<p>Apply the database migrations and create a superuser to access the Django admin interface:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker-compose exec web python manage.py migrate\ndocker-compose exec web python manage.py createsuperuser\n<\/pre><\/div>\n\n\n<p>By adding PostgreSQL support, we\u2019ve enhanced our Django project, making it more suitable for production environments. Running PostgreSQL in a Docker container ensures that our database setup remains consistent and isolated, just like our application environment.<\/p>\n\n\n\n<p>Now, you should be able to log in to the admin portal on your Docker-running web site at <a href=\"http:\/\/localhost:8000\/admin\/\">http:\/\/localhost:8000\/admin\/<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1160\" height=\"345\" src=\"https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.13.00%E2%80%AFPM.png?resize=1160%2C345&#038;ssl=1\" alt=\"Shows the initial view of the Django admin portal.\" class=\"wp-image-1823\" srcset=\"https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.13.00%E2%80%AFPM.png?resize=1160%2C345&amp;ssl=1 1160w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.13.00%E2%80%AFPM.png?resize=800%2C238&amp;ssl=1 800w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.13.00%E2%80%AFPM.png?resize=1536%2C457&amp;ssl=1 1536w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.13.00%E2%80%AFPM.png?resize=120%2C36&amp;ssl=1 120w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.13.00%E2%80%AFPM.png?resize=90%2C27&amp;ssl=1 90w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.13.00%E2%80%AFPM.png?resize=320%2C95&amp;ssl=1 320w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.13.00%E2%80%AFPM.png?resize=560%2C167&amp;ssl=1 560w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.13.00%E2%80%AFPM.png?w=1890&amp;ssl=1 1890w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/figure>\n\n\n\n<h2 id=\"set-up-django-with-docker-postgresql-and-react\" class=\"wp-block-heading\">Set up Django with Docker, PostgreSQL and React<\/h2>\n\n\n\n<p>In this section, we will configure our Django application to work with React. This involves setting up JavaScript and assets, compiling them into a bundle, and serving them from our development server.<\/p>\n\n\n\n<h3 id=\"install-node-and-npm\" class=\"wp-block-heading\">Install Node and NPM<\/h3>\n\n\n\n<p>Before setting up JavaScript and React, you\u2019ll need to have Node.js and npm installed on your system. npm is the package manager for Node.js and is required for installing JavaScript dependencies.<\/p>\n\n\n\n<p>First, <strong>download Node.js<\/strong>: Visit the <a href=\"https:\/\/nodejs.org\/\">official Node.js website<\/a> and download the LTS (Long-Term Support) version for your operating system. This version includes npm.<\/p>\n\n\n\n<p>Then, <strong>install Node.js<\/strong>, following the instructions for your operating system. For Windows, run the installers and follow the prompts. For Macs, download the .pkg installer and follow the prompts or alternately install with Homebrew (<em>brew install node<\/em>).<\/p>\n\n\n\n<h3 id=\"set-up-javascript\" class=\"wp-block-heading\"><strong>Set Up JavaScript<\/strong><\/h3>\n\n\n\n<p>First, create a new subfolder under the root of your project to store JavaScript files, \/assets.<\/p>\n\n\n\n<p>Then, run the following commands in the root folder to set up the necessary Node packages and modules:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nnpm init -y\nnpm install webpack webpack-cli --save-dev\n<\/pre><\/div>\n\n\n<h3 id=\"create-a-sample-javascript-file\" class=\"wp-block-heading\"><strong>Create a Sample JavaScript File<\/strong><\/h3>\n\n\n\n<p>Create assets\/index.js with the following content:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nfunction component() {\n  const element = document.createElement('div');\n  element.innerHTML = 'Hello Beautiful';\n  return element;\n}\n\ndocument.body.appendChild(component());\n<\/pre><\/div>\n\n\n<p>This basic JavaScript file will serve as our entry point for Webpack.<\/p>\n\n\n\n<h3 id=\"create-webpack-configuration-file\" class=\"wp-block-heading\"><strong>Create Webpack Configuration File<\/strong><\/h3>\n\n\n\n<p>Create webpack.config.js with the following content:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nconst path = require('path');\n\nmodule.exports = {\n  entry: '.\/assets\/index.js',\n  output: {\n    filename: 'index-bundle.js',\n    path: path.resolve(__dirname, '.\/static'),\n  },\n};\n<\/pre><\/div>\n\n\n<p>This configuration tells Webpack to take index.js as the entry point and output the bundled file as index-bundle.js in the static directory.<\/p>\n\n\n\n<h3 id=\"update-package-json\" class=\"wp-block-heading\"><strong>Update package.json<\/strong><\/h3>\n\n\n\n<p>Add the following script to package.json:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n&quot;scripts&quot;: {\n  &quot;dev&quot;: &quot;webpack --mode development --watch&quot;\n}\n<\/pre><\/div>\n\n\n<p>This script runs Webpack in development mode and watches for changes to recompile automatically.<\/p>\n\n\n\n<h3 id=\"run-webpack\" class=\"wp-block-heading\"><strong>Run Webpack<\/strong><\/h3>\n\n\n\n<p>To compile the JavaScript files, run:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nnpm run dev\n<\/pre><\/div>\n\n\n<h3 id=\"configure-django-to-use-static-files\" class=\"wp-block-heading\"><strong>Configure Django to Use Static Files<\/strong><\/h3>\n\n\n\n<p>Update the Django settings file to include the configuration for static files:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nimport os\nSTATIC_URL = '\/static\/'\nSTATICFILES_DIRS = &#x5B;\n    os.path.join(BASE_DIR, 'static'),\n]\nSTATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')\n<\/pre><\/div>\n\n\n<p>This tells Django where to find and serve static files.<\/p>\n\n\n\n<h3 id=\"install-babel\" class=\"wp-block-heading\"><strong>Install Babel<\/strong><\/h3>\n\n\n\n<p>To enable ES6 and JSX syntax, install Babel:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nnpm install --save-dev babel-loader @babel\/core @babel\/preset-env @babel\/preset-react\n<\/pre><\/div>\n\n\n<h3 id=\"update-webpack-configuration-for-babel\" class=\"wp-block-heading\"><strong>Update Webpack Configuration for Babel<\/strong><\/h3>\n\n\n\n<p>Update webpack.config.js to include Babel configuration:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nconst path = require('path');\n\nmodule.exports = {\n  entry: '.\/assets\/index.js',\n  output: {\n    filename: 'index-bundle.js',\n    path: path.resolve(__dirname, '.\/static'),\n  },\n  module: {\n    rules: &#x5B;\n      {\n        test: \/\\.(js|jsx)$\/,\n        exclude: \/node_modules\/,\n        loader: 'babel-loader',\n        options: { presets: &#x5B;'@babel\/preset-env', '@babel\/preset-react'] },\n      },\n      {\n        test: \/\\.css$\/,\n        use: &#x5B;\n          'style-loader',\n          {\n            loader: 'css-loader',\n            options: {\n              modules: true,\n            },\n          },\n        ],\n      },\n    ],\n  },\n};\n<\/pre><\/div>\n\n\n<h3 id=\"install-react\" class=\"wp-block-heading\"><strong>Install React<\/strong><\/h3>\n\n\n\n<p>Finally, install React and ReactDOM:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nnpm install --save react react-dom\n<\/pre><\/div>\n\n\n<p>By following these steps, you have configured your Django project to work seamlessly with React, allowing you to build a modern front-end application while leveraging Django\u2019s robust back-end capabilities. This setup ensures your JavaScript files are compiled and served efficiently, providing a smooth development experience.<\/p>\n\n\n\n<h3 id=\"ok-but-whats-node\" class=\"wp-block-heading\">Ok, But What&#8217;s Node??<\/h3>\n\n\n\n<p>As a more traditional &#8216;back-end&#8217; developer, some of this new Javascript stack is indeed confusing. Here&#8217;s one way of thinking about it.<\/p>\n\n\n\n<p>Node.js is a runtime environment that allows you to run JavaScript on the server side, essential for tools like npm, Webpack, and Babel. npm is the package manager for Node.js, used to install and manage dependencies. Webpack bundles your JavaScript files and assets, compiling them into a single file. Babel transforms modern JavaScript and JSX syntax into a format compatible with older browsers. React is a library for building user interfaces. Together, these tools enable you to create a modern front-end application with React, manage dependencies efficiently, and ensure compatibility, while your Django backend serves the bundled output.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Node.js<\/strong> is like the Python interpreter itself. Just as Node.js runs JavaScript code, the Python interpreter runs Python code.<\/li>\n\n\n\n<li><strong>npm<\/strong> (Node Package Manager) is similar to <strong>pip<\/strong> (Python Package Installer). Both are used to install and manage libraries and dependencies for their respective languages.<\/li>\n\n\n\n<li><strong>Webpack<\/strong> is analogous to <strong>Django\u2019s staticfiles app<\/strong> or tools like <strong>whitenoise<\/strong>. While Webpack bundles JavaScript and assets, Django\u2019s staticfiles app collects and serves static files (CSS, JavaScript, images).<\/li>\n\n\n\n<li><strong>Babel<\/strong> is comparable to <strong>transpilers or compilers<\/strong> in other contexts, but for Python, you might think of tools like <strong>2to3<\/strong>, which convert Python 2 code to Python 3, ensuring compatibility.<\/li>\n\n\n\n<li><strong>React<\/strong> is akin to <strong>Django templates<\/strong> or <strong>Jinja2 templates<\/strong>, but more interactive. While Django templates render HTML on the server side, React components render dynamic interfaces on the client side.<\/li>\n<\/ul>\n\n\n\n<p>I found this article on <a href=\"https:\/\/www.saaspegasus.com\/guides\/modern-javascript-for-django-developers\/\">Modern JavaScript for Django Developers<\/a> critically helpful along the way.<\/p>\n\n\n\n<h2 id=\"testing-the-react-integration\" class=\"wp-block-heading\"><strong>Testing the React Integration<\/strong><\/h2>\n\n\n\n<p>In this section, we\u2019ll test that React is working by creating a new URL endpoint, setting up a basic HTML template, and configuring Django to serve the bundled JavaScript file.<\/p>\n\n\n\n<h3 id=\"create-a-new-url-endpoint\" class=\"wp-block-heading\"><strong>Create a New URL Endpoint<\/strong><\/h3>\n\n\n\n<p>First, add a new URL endpoint in your Django project\u2019s urls.py file to serve a template where React will be mounted. Add the following line:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nfrom django.urls import path\nfrom django.views.generic import TemplateView\n\nurlpatterns = &#x5B;\n    path('base', TemplateView.as_view(template_name='base.html')),\n    # other paths...\n]\n<\/pre><\/div>\n\n\n<p>This creates a new URL endpoint base that renders the base.html template.<\/p>\n\n\n\n<h2 id=\"create-the-base-html-template\" class=\"wp-block-heading\"><strong>Create the Base HTML Template<\/strong><\/h2>\n\n\n\n<p>Next, create the base.html template in your templates directory. If you don\u2019t already have a templates folder, create one in the root of your project. Inside the templates folder, create a file named base.html with the following content:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n{% load static %}\n&lt;!doctype html&gt;\n&lt;html&gt;\n  &lt;head&gt;\n    &lt;title&gt;Why is this so complicated?&lt;\/title&gt;\n  &lt;\/head&gt;\n  &lt;body&gt;\n    &lt;div id=&quot;root&quot;&gt;&lt;\/div&gt;\n    &lt;script src=&quot;{% static 'index-bundle.js' %}&quot;&gt;&lt;\/script&gt;\n  &lt;\/body&gt;\n&lt;\/html&gt;\n<\/pre><\/div>\n\n\n<p>This HTML template loads the index-bundle.js file that Webpack generates and provides a div with the id root where React will mount.<\/p>\n\n\n\n<h3 id=\"configure-django-to-look-for-templates\" class=\"wp-block-heading\"><strong>Configure Django to Look for Templates<\/strong><\/h3>\n\n\n\n<p>Ensure that Django knows where to look for your templates. In your project\u2019s settings.py file, add the templates directory to the TEMPLATES setting:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nTEMPLATES = &#x5B;\n    {\n        'BACKEND': 'django.template.backends.django.DjangoTemplates',\n        'DIRS': &#x5B;BASE_DIR \/ 'templates'],  # Make sure this path is correct\n        'APP_DIRS': True,\n        'OPTIONS': {\n            'context_processors': &#x5B;\n                'django.template.context_processors.debug',\n                'django.template.context_processors.request',\n                'django.contrib.auth.context_processors.auth',\n                'django.contrib.messages.context_processors.messages',\n            ],\n        },\n    },\n]\n<\/pre><\/div>\n\n\n<p>This configuration tells Django to look for templates in the templates directory.<\/p>\n\n\n\n<h3 id=\"update-dockerfile-to-collect-static-files\" class=\"wp-block-heading\"><strong>Update Dockerfile to Collect Static Files<\/strong><\/h3>\n\n\n\n<p>Finally, update your Dockerfile to collect static files when building the Docker image. Add the following line to your Dockerfile:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n# Other RUN commands...\n\n# Collect static files\nRUN python manage.py collectstatic --noinput\n<\/pre><\/div>\n\n\n<p>This command collects all static files into the location specified by STATIC_ROOT.<\/p>\n\n\n\n<h3 id=\"verify-the-setup\" class=\"wp-block-heading\"><strong>Verify the Setup<\/strong><\/h3>\n\n\n\n<p><strong>Rebuild and Start Docker Containers<\/strong>: After making these changes, rebuild your Docker image and start the containers:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker-compose down\ndocker-compose up --build\n<\/pre><\/div>\n\n\n<p><strong>Access the New Endpoint<\/strong>: Open your web browser and navigate to <a href=\"http:\/\/localhost:8000\/base\">http:\/\/localhost:8000\/base<\/a>. You should see a page with \u201cHello Beautiful\u201d displayed, indicating that the React integration is working correctly.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"720\" height=\"400\" src=\"https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.45.19%E2%80%AFPM.png?resize=720%2C400&#038;ssl=1\" alt=\"Hello Beautiful showing in a Chrome browser tab.\" class=\"wp-image-1829\" style=\"width:401px;height:auto\" srcset=\"https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.45.19%E2%80%AFPM.png?w=720&amp;ssl=1 720w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.45.19%E2%80%AFPM.png?resize=120%2C67&amp;ssl=1 120w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.45.19%E2%80%AFPM.png?resize=90%2C50&amp;ssl=1 90w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.45.19%E2%80%AFPM.png?resize=320%2C178&amp;ssl=1 320w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-9.45.19%E2%80%AFPM.png?resize=560%2C311&amp;ssl=1 560w\" sizes=\"auto, (max-width: 720px) 100vw, 720px\" \/><\/figure>\n\n\n\n<h2 id=\"development-workflow\" class=\"wp-block-heading\">Development Workflow<\/h2>\n\n\n\n<p>Here&#8217;s a sample workflow for using all this stuff to develop.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Run npm run dev locally<\/strong>:\n<ul class=\"wp-block-list\">\n<li>This command will start webpack in watch mode, so it monitors your JavaScript files for changes and automatically rebuilds them.<\/li>\n\n\n\n<li>The generated files will be placed in the \/static directory as specified in the webpack.config.js.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Mount the Code to Docker<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Since your code is mounted to Docker (as specified in the docker-compose.yml file), any changes made locally will be reflected inside the Docker container.<\/li>\n\n\n\n<li>This includes the updated JavaScript files in the \/static directory.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Docker Setup<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Ensure Docker is running and your containers are up by using <em>docker-compose up<\/em>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>There are likely many alternatives to this setup. One, for example, would be having Docker build the Javascript bundle, incorporating the build steps into the Dockerfile and ensuring the Docker container runs webpack. I readily admit I have been unable to make this work!<\/p>\n\n\n\n<h2 id=\"auto-run-migrations\" class=\"wp-block-heading\">Auto-Run Migrations<\/h2>\n\n\n\n<p>Adding an entrypoint script to handle database readiness and run migrations before starting the Django server is a good practice. It ensures that your application doesn\u2019t start before the database is ready and that any necessary migrations are applied automatically. Here\u2019s how you can integrate this into your Docker setup:<\/p>\n\n\n\n<h3 id=\"update-dockerfile\" class=\"wp-block-heading\"><strong>Update Dockerfile<\/strong><\/h3>\n\n\n\n<p>Add the following lines to the end of your Dockerfile:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n# Install dependencies\nRUN apt-get update \\\n    &amp;&amp; apt-get install -y netcat-openbsd\n\n# Copy the entrypoint script\nCOPY entrypoint.sh \/entrypoint.sh\n\n# Make the entrypoint script executable\nRUN chmod +x \/entrypoint.sh\n\n# Set the entrypoint script to run when the container starts\nENTRYPOINT &#x5B;&quot;\/entrypoint.sh&quot;]\n<\/pre><\/div>\n\n\n<h3 id=\"create-the-entrypoint-sh-file\" class=\"wp-block-heading\"><strong>Create the entrypoint.sh File<\/strong><\/h3>\n\n\n\n<p>Create a file named entrypoint.sh in the root of your project with the following content:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\n#!\/bin\/sh\n\n# Wait for the database to be ready\necho &quot;Waiting for PostgreSQL to start...&quot;\nwhile ! nc -z db 5432; do\n  sleep 0.1\ndone\necho &quot;PostgreSQL started&quot;\n\n# Run Django migrations\necho &quot;Running migrations&quot;\npython manage.py migrate --noinput\n\n# Start the Django app\nexec &quot;$@&quot;\n<\/pre><\/div>\n\n\n<p>By adding the entrypoint script, you ensure that the Django server waits for the PostgreSQL database to be ready and that migrations are applied before starting the application. This approach improves the robustness and reliability of your Dockerized Django project.<\/p>\n\n\n\n<h2 id=\"debugging\" class=\"wp-block-heading\">Debugging<\/h2>\n\n\n\n<p>There&#8217;s a good chance you&#8217;ll want to run your Python code directly from your IDE such as for debugging while still connecting to the PostgreSQL database running inside a Docker container. Here\u2019s how you can set this up.<\/p>\n\n\n\n<h3 id=\"expose-postgresql-in-docker\" class=\"wp-block-heading\"><strong>Expose PostgreSQL in Docker<\/strong><\/h3>\n\n\n\n<p>First, ensure your docker-compose.yml file is configured to expose the PostgreSQL service. This setup allows your local environment to access the database running in the Docker container.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nversion: '3.8'\nservices:\n  db:\n    image: postgres\n    environment:\n       - &quot;POSTGRES_HOST_AUTH_METHOD=trust&quot;\n    ports:\n      - &quot;5433:5432&quot;  # Expose the PostgreSQL port\n    volumes:\n      - postgres_data:\/var\/lib\/postgresql\/data\n  web:\n    build: .\n    command: python manage.py runserver 0.0.0.0:8000\n    volumes:\n      - .:\/app\n    ports:\n      - &quot;8000:8000&quot;\n    depends_on:\n      - db\nvolumes:\n  postgres_data:\n<\/pre><\/div>\n\n\n<p>This configuration exposes the PostgreSQL port 5432 on your localhost, making it accessible to applications running on your local machine.<\/p>\n\n\n\n<h3 id=\"update-django-settings\" class=\"wp-block-heading\"><strong>Update Django Settings<\/strong><\/h3>\n\n\n\n<p>Next, update your Django settings to connect to the PostgreSQL database exposed on localhost when running locally. We&#8217;ll need to start using environment variables to accomplish this. First, add a new debug configuration into PyCharm that executes manage.py runserver, but adds a new Environment Variable, DJANGO_ENV=debug.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1160\" height=\"499\" src=\"https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-10.38.26%E2%80%AFPM.png?resize=1160%2C499&#038;ssl=1\" alt=\"How to debug a project that uses Django, Docker, PostgreSQL and React.\" class=\"wp-image-1839\" srcset=\"https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-10.38.26%E2%80%AFPM.png?resize=1160%2C499&amp;ssl=1 1160w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-10.38.26%E2%80%AFPM.png?resize=800%2C344&amp;ssl=1 800w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-10.38.26%E2%80%AFPM.png?resize=1536%2C660&amp;ssl=1 1536w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-10.38.26%E2%80%AFPM.png?resize=2048%2C880&amp;ssl=1 2048w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-10.38.26%E2%80%AFPM.png?resize=120%2C52&amp;ssl=1 120w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-10.38.26%E2%80%AFPM.png?resize=90%2C39&amp;ssl=1 90w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-10.38.26%E2%80%AFPM.png?resize=320%2C138&amp;ssl=1 320w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-10.38.26%E2%80%AFPM.png?resize=560%2C241&amp;ssl=1 560w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-10.38.26%E2%80%AFPM.png?resize=1920%2C825&amp;ssl=1 1920w, https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-2024-06-05-at-10.38.26%E2%80%AFPM.png?w=2066&amp;ssl=1 2066w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/figure>\n\n\n\n<p>Then, in your settings file, update the database settings to look for this new environment variable:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nimport os\nDJANGO_ENV = os.environ.get('DJANGO_ENV', 'production')  # Defaults to 'production' if not set\n\nif DJANGO_ENV == 'debug':\n    DATABASES = {\n        'default': {\n            'ENGINE': 'django.db.backends.postgresql',\n            'NAME': 'postgres',\n            'USER': 'postgres',\n            'PASSWORD': 'postgres',\n            'HOST': 'localhost',\n            'PORT': '5433',  # Use port 5433 for local debug environment\n        }\n    }\nelse:\n    DATABASES = {\n        'default': {\n            'ENGINE': 'django.db.backends.postgresql',\n            'NAME': 'postgres',\n            'USER': 'postgres',\n            'PASSWORD': 'postgres',\n            'HOST': 'db',  # Docker Compose service name as the host\n            'PORT': '5432',  # Default PostgreSQL port\n        }\n    }\n<\/pre><\/div>\n\n\n<p>This tells Django to connect to the PostgreSQL database on localhost:5433 when running in debug mode.<\/p>\n\n\n\n<h3 id=\"run-the-postgresql-container\" class=\"wp-block-heading\"><strong>Run the PostgreSQL Container<\/strong><\/h3>\n\n\n\n<p>Start just the PostgreSQL container using Docker Compose. Run the following command:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndocker-compose up db\n<\/pre><\/div>\n\n\n<p>This command starts the PostgreSQL container without starting the Django container. <\/p>\n\n\n\n<h3 id=\"run-and-debug\" class=\"wp-block-heading\"><strong>Run and Debug<\/strong><\/h3>\n\n\n\n<p>Some IDEs will let you remote connect to a running service. In this particular example, we&#8217;re going to run a new instance locally and connect to the remote db. Assuming a clean local virtual environment, you may need to install the db driver locally:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\npip install psycopg2-binary\n<\/pre><\/div>\n\n\n<p>Now you can run your Django project from the IDE. It will connect to the PostgreSQL database running inside the Docker container. You can also use the IDE\u2019s debugging tools to set breakpoints and debug your application as usual.<\/p>\n\n\n\n<h2 id=\"summary\" class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>In this guide, we\u2019ve walked through how to set up Django with Docker, PostgreSQL, and React. Starting from the basics of project setup with Pipenv and Django, we moved on to containerizing our application with Docker for consistent development and production environments. We then upgraded our database to PostgreSQL, and integrated React, utilizing Webpack and Babel to manage our JavaScript assets efficiently.<\/p>\n\n\n\n<p>It&#8217;s a lot to sort out when all you really wanted was a website. I hope someone finds this useful!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Figuring out how to set up Django with Docker, PostgreSQL, and React can be a complex task, especially if you, like me, don&#8217;t really code much nowadays. The boilerplate effort&hellip;<\/p>\n","protected":false},"author":1,"featured_media":1851,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[64,46],"tags":[],"powerkit_post_featured":[],"class_list":{"0":"post-1807","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-application-development","8":"category-projects"},"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.craigperler.com\/blog\/wp-content\/uploads\/2024\/06\/DALL%C2%B7E-2024-06-05-23.35.39-A-high-tech-futuristic-image-of-a-sleek-laptop-displaying-code-on-the-screen.-The-background-is-filled-with-digital-elements-like-floating-data-strea.webp?fit=1792%2C1024&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p1SwZ6-t9","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/posts\/1807","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/comments?post=1807"}],"version-history":[{"count":5,"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/posts\/1807\/revisions"}],"predecessor-version":[{"id":1853,"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/posts\/1807\/revisions\/1853"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/media\/1851"}],"wp:attachment":[{"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/media?parent=1807"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/categories?post=1807"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/tags?post=1807"},{"taxonomy":"powerkit_post_featured","embeddable":true,"href":"https:\/\/www.craigperler.com\/blog\/wp-json\/wp\/v2\/powerkit_post_featured?post=1807"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}