How to Set Up a Multi-container Web Application with Docker Compose

Learning how to set up a multi-container web application with Docker Compose transforms complex deployments into manageable, reproducible processes. Docker Compose simplifies orchestrating multiple containers that work together as a complete application stack. This tutorial walks you through creating a production-ready web application using separate containers for your web server, database, and application code.

Modern web applications rarely run on single servers anymore. They typically require databases, caching layers, web servers, and application containers working in harmony. Docker Compose eliminates the complexity of managing these interconnected services manually. You’ll gain practical skills for deploying scalable applications that can run consistently across development, staging, and production environments.

By the end of this guide, you’ll have a fully functional multi-container setup running a web application with a database backend. You’ll understand how containers communicate, share data, and maintain persistent storage. This knowledge applies to any technology stack, whether you’re deploying WordPress sites, Node.js applications, or Python web services.

Prerequisites and Requirements for Multi-container Web Application Setup

Before diving into how to set up a multi-container web application with Docker Compose, ensure your system meets these requirements. You’ll need Docker and Docker Compose installed on your Linux server or local development machine. Most modern Linux distributions include Docker in their package repositories.

Your system should have at least 2GB of RAM available for containers. While Docker can run on less memory, multi-container applications perform better with adequate resources. You’ll also need basic familiarity with command-line operations and text editors like nano or vim.

Install Docker using your distribution’s package manager:

sudo apt update
sudo apt install docker.io docker-compose -y
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker $USER

Log out and back in for group membership changes to take effect. Verify your installation works correctly:

docker --version
docker-compose --version

You should see version numbers for both commands. Create a project directory where you’ll build your multi-container application:

mkdir ~/webapp-docker
cd ~/webapp-docker

This tutorial takes approximately 30-45 minutes to complete. Having a text editor ready and basic understanding of YAML syntax will help you follow along more easily.

Step-by-Step Guide to Setting Up Multi-container Web Applications with Docker Compose

Related article: How to Configure Ssh Key Authentication and Disable Password Login on Linux Servers

Step 1: Create the Docker Compose Configuration File

Start by creating the main Docker Compose file that defines your application services. This file orchestrates how containers interact with each other:

nano docker-compose.yml

Add the following configuration for a web application with database support:

version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - app
    networks:
      - webapp-network

  app:
    image: php:7.4-fpm
    volumes:
      - ./html:/var/www/html
    depends_on:
      - database
    networks:
      - webapp-network

  database:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: webapp_db
      MYSQL_USER: webapp_user
      MYSQL_PASSWORD: webapp_pass
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - webapp-network

volumes:
  db_data:

networks:
  webapp-network:
    driver: bridge

Step 2: Configure the Web Server

Create an Nginx configuration file to handle web requests and forward PHP processing to the application container:

nano nginx.conf

Add this configuration:

events {
    worker_connections 1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    server {
        listen 80;
        server_name localhost;
        root /usr/share/nginx/html;
        index index.php index.html;

        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }

        location ~ .php$ {
            fastcgi_pass app:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
    }
}

Step 3: Create Application Files

Set up your web application files in the html directory:

mkdir html
nano html/index.php

Create a simple PHP application that connects to the database:

setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    echo "

Multi-container Web Application

"; echo "

Database connection: Successful The How to Set Up a Multi-container Web Application with Docker Compose stands as a significant historical event.

"; echo "

Container hostname: " . gethostname() . "

"; echo "

Current time: " . date('Y-m-d H:i:s') . "

"; } catch(PDOException $e) { echo "

Database Connection Failed

"; echo "

Error: " . $e->getMessage() . "

"; } ?>

Step 4: Launch Your Multi-container Application

Start all services using Docker Compose. This command reads your configuration file and creates the entire application stack:

docker-compose up -d

The -d flag runs containers in detached mode. Monitor the startup process:

docker-compose logs -f

Wait for all services to initialize completely. You should see messages indicating that Nginx, PHP-FPM, and MySQL have started successfully.

Step 5: Verify Container Communication

Check that all containers are running and can communicate with each other:

docker-compose ps

Test your application by visiting http://localhost in your web browser. You should see the application page showing a successful database connection.

Examine container logs if something isn’t working:

docker-compose logs web
docker-compose logs app
docker-compose logs database

Step 6: Test Data Persistence

Create a test table in your database to verify data persistence works correctly:

docker-compose exec database mysql -u webapp_user -p webapp_db

Enter the password webapp_pass when prompted, then create a test table:

CREATE TABLE test_table (id INT AUTO_INCREMENT PRIMARY KEY, message VARCHAR(255));
INSERT INTO test_table (message) VALUES ('Multi-container setup working!');
SELECT  FROM test_table;
EXIT;

Restart your containers and verify the data persists:

docker-compose restart
docker-compose exec database mysql -u webapp_user -p webapp_db -e "SELECT  FROM test_table;"

Troubleshooting Common Multi-container Docker Compose Issues

When learning how to set up a multi-container web application with Docker Compose, you might encounter several common problems. Understanding these issues helps you debug and maintain your applications effectively.

Port Conflicts

If port 80 is already in use, you’ll see binding errors. Change the port mapping in your docker-compose.yml file:

ports:
  - "8080:80"

Then access your application at http://localhost:8080 instead.

Database Connection Issues

Container networking problems often manifest as database connection failures. Ensure all services use the same network and reference containers by their service names. The official Docker Compose networking documentation provides detailed troubleshooting steps.

Check network connectivity between containers:

docker-compose exec app ping database

Permission Problems

File permission issues can prevent PHP from reading files or Nginx from serving content. Fix ownership and permissions:

sudo chown -R $USER:$USER html/
chmod -R 755 html/

Memory and Resource Constraints

Multi-container applications consume more resources than single containers. Monitor resource usage:

docker stats

Add resource limits to your docker-compose.yml if needed:

app:
  image: php:7.4-fpm
  deploy:
    resources:
      limits:
        memory: 512M

Container Startup Order

Sometimes containers start before their dependencies are ready. The depends_on directive ensures startup order but doesn’t wait for services to be fully ready. For complex applications, consider using health checks or wait scripts.

Log Analysis

Always check container logs when troubleshooting. Use specific service names to focus on problematic containers:

docker-compose logs --tail=50 database

The Docker Compose file reference contains comprehensive configuration options for resolving complex issues.

Optimizing and Scaling Your Docker Compose Setup

Your multi-container web application can be enhanced with additional features and optimizations. Consider implementing environment-specific configurations using multiple Compose files. Create separate files for development, staging, and production environments.

Add monitoring and logging solutions to

Similar Posts