Web App Development with Docker Compose

Docker Compose is a powerful tool that simplifies managing multi-container Docker applications, making it especially useful for web app development. With Docker Compose, you can easily define and manage services like databases, web servers, and other dependencies in a single configuration.
In this guide, we’ll walk you through how to leverage Docker Compose and Nginx to efficiently set up a local development and production-ready environment for a Django application with PostgreSQL as the database. This guide will provide a real-world example of how Docker Compose, Gunicorn, and Nginx can work together to streamline web application deployment.
While we focus on setting up the environment with Docker, we won’t go into deep details on Django’s internal structure. However, this guide will help you understand how to efficiently containerize and deploy a Django app using Nginx as a reverse proxy.
The project files for this section are available in our GitHub repository. If you'd prefer to skip the detailed steps of Django web app development, simply clone the project files and proceed to Step 12.
If you'd like to learn more about Django, check out our Django Introduction Guide.
Step 1: Set Up Project Environment
Before configuring Docker and Docker Compose, we need to set up the project directory structure to support Django, PostgreSQL, and Nginx.
By running the commands below, you'll have the following project structure in place, ready for Docker Compose to orchestrate the services:
mkdir ch6-docker-compose-demo && cd ch6-docker-compose-demo
mkdir -p django postgres/data nginx
touch docker-compose.yml django/Dockerfile django/requirements.txt nginx/nginx.conf
Project Structure:
ch6-docker-compose-demo/
├── django/
│ ├── Dockerfile
│ ├── requirements.txt
├── nginx/
│ ├── nginx.conf
├── postgres/
│ ├── data/
├── docker-compose.yml
Step 2: Write the Dockerfile for Django
To containerize our Django application, we'll create a Dockerfile. This file defines the steps to build a Docker image for our Django app, ensuring that it has all the necessary dependencies and is set up to run smoothly inside a container.
In this step, we'll walk you through writing the Dockerfile
for Django. This file will specify the base image, install dependencies, copy project files, and configure the app to run inside the container. Using Docker Compose, we can then manage this container alongside other services like the database.
Add the following content to the django/
Dockerfile
:
FROM python:3.9-slim
WORKDIR /app
RUN apt-get update && apt-get install -y \
libpq-dev gcc && \
rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "config.wsgi:application"]
Explanation of the Dockerfile:
- FROM python:3.9-slim: Python 3.9 slim image is a lightweight version of Python that contains the essentials needed to run a Python app, reducing the overall image size.
- WORKDIR /app: This sets
/app
as the working directory inside the container. All subsequent commands will run in this directory. - RUN apt-get update && apt-get install -y libpq-dev gcc && rm -rf /var/lib/apt/lists/: Install necessary system packages like
libpq-dev
(needed for PostgreSQL database interaction) andgcc
(a C compiler required for some Python dependencies). After the installation, we clean up the package list to minimize the image size. - COPY requirements.txt .: copies the
requirements.txt
file from your local project into the container. This file contains the list of Python dependencies required by the project. - RUN pip install --no-cache-dir -r requirements.txt: This command installs the dependencies listed in
requirements.txt
using pip. The--no-cache-dir
option ensures that pip doesn’t store cached files, further reducing the image size. - COPY . .: Copies all the files from the current directory (i.e., your Django app) into the container's
/app
directory. - RUN python manage.py collectstatic --noinput: This command collects static files before running the app
- CMD ["gunicorn", "--bind", "0.0.0.0:8000", "config.wsgi:application"]: Finally, we specify the command to start the application using Gunicorn, a production-grade web server for Python applications. This command binds the app to
0.0.0.0:8000
(making it accessible externally on port 8000) and tells it to use the WSGI entry point inconfig.wsgi:application
to run the app.
Step 3: Write the docker-compose.yml File
In this step, we'll define the Docker Compose configuration that will set up the necessary containers for our Django application, PostgreSQL database, and Nginx server. Docker Compose allows us to define multi-container applications in a single YAML file, which simplifies the process of starting and managing our environment with just one command. This configuration will not only build the web app contai
Subscribe now for
uninterrupted access.