Running a Multi-Container Web App with Docker Compose
Tags: devops, docker, fullstack, hnginternship
Published: 2024-07-16 09:09:31

Using Docker Compose, this tutorial shows you how to launch a full-stack web application. The program is composed of distinct services for the database (PostgreSQL), frontend (React), and backend (Python). Nginx serves as a security and efficiency reverse proxy.

This is a DevOps project for my HNG internship and was done with a provided Git [repo](https://github.com/hngprojects/devops-stage-2)

*Understanding the Services:*

* **Backend:** Built using Python (uvicorn), served on port 8000. 
* **Frontend:** Built with React, served on port 5173.
* **Database:** PostgreSQL, configured with username, password, and database name.
* **Traefik:** A reverse proxy for managing traffic and routing requests.

*Requirements:*

* A cloud instance (e.g., EC2) with Docker installed.
* The instance has npm and Node.js installed.
* An account on Docker Hub.
* A unique domain name (free from freedns.afraid.org).

### Procedure

1. Fork the provided repository and clone it to your instance.
2. Configure the Frontend:
   * Install Node.js and npm.
   * Modify the vite.config.ts file so that port 5173 is accessible.
   * Execute `npm run dev` and `npm install`.
   * Configure the security group for your instance to accept incoming traffic on port 5173. Using port 5173 and your instance's public IP address, access the frontend.

3. Containerize the Frontend:
   * In the frontend directory, create a Dockerfile. Build the React application, expose port 80, install dependencies, use the official Node.js image, and copy the application code.
   * Use `docker build` to create the Docker image.

4. Build a Backend Container:
   * In the backend directory, make a Dockerfile.
   * Install Poetry and its dependencies, use the official Python image, copy the application code, configure environment variables, and open port 8000.
   * Make a `.dockerignore` file to remove files from the image that aren't needed.
   * Use `docker build` to create the Docker image.

5. Create a Docker Compose file (docker-compose.yml):
   * Specify the frontend, backend, database, and Traefik services.
   * For routing requests, use Traefik as a reverse proxy with labels.
   * Set environment variables to configure the database service's connection details.
   * Configure the database URL's environment variables in the backend service.
   * To define paths for producing frontend and backend images, use the build context.
   * Establish networks for service-to-service communication.

6. Configure Your Domain Name:
   * Make a subdomain using a free DNS provider. Set the subdomain's address to the public IP address of your instance.
   * For the frontend service, update the docker-compose.yml file with your domain name.

7. **Run the application:**
   * To create and start all services in detached mode, run `docker-compose up -d`.

Advantages of Docker Compose usage:

* **Simplified Multi-Container Management:** Defines and runs all services in a single configuration file.
* **Scalability:** Easily add or remove containers as needed.
* **Reproducibility:** Ensures consistent environments across development, testing, and production.

This approach provides a solid foundation for deploying web applications using Docker containers and a reverse proxy for enhanced security and performance.

Check out the full project on GitHub: [Explore the Code](https://github.com/teetoflame/devops-stage-2)