Multi-Container Application Setup with Docker

Learn how to set up a complete multi-container application stack with Docker run commands. Covers networking, shared volumes, environment configuration, and orchestrating dependent services.

Real-World Stacks

Detailed Explanation

Building a Complete Application Stack

Most real applications consist of multiple services: a web server, an API, a database, and a cache. While Docker Compose is the standard tool for multi-container orchestration, understanding how to wire containers together with docker run gives you deeper knowledge of how Docker networking and linking work.

Example Stack: Web + API + Database + Cache

Let's build a four-container stack step by step:

Step 1: Create a shared network

docker network create myapp-net

Step 2: Start the database

docker run -d \
  --name myapp-db \
  --network myapp-net \
  --restart unless-stopped \
  -e POSTGRES_USER=app \
  -e POSTGRES_PASSWORD=dbpass123 \
  -e POSTGRES_DB=myapp \
  -v myapp-pgdata:/var/lib/postgresql/data \
  postgres:16

Step 3: Start the cache

docker run -d \
  --name myapp-cache \
  --network myapp-net \
  --restart unless-stopped \
  --memory 256m \
  redis:7-alpine \
  redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru

Step 4: Start the API server

docker run -d \
  --name myapp-api \
  --network myapp-net \
  --restart unless-stopped \
  -e DATABASE_URL=postgres://app:dbpass123@myapp-db:5432/myapp \
  -e REDIS_URL=redis://myapp-cache:6379 \
  -e NODE_ENV=production \
  my-api-image

Step 5: Start the web server (reverse proxy)

docker run -d \
  --name myapp-web \
  --network myapp-net \
  --restart unless-stopped \
  -p 80:80 \
  -p 443:443 \
  -v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf:ro \
  nginx:alpine

Service Start Order

Containers should start in dependency order:

  1. Database (no dependencies)
  2. Cache (no dependencies)
  3. API (depends on database and cache)
  4. Web (depends on API)

Unlike Docker Compose, docker run does not have built-in dependency management. Your application should implement connection retry logic to handle temporary unavailability during startup.

Health Checks

Add health checks to verify services are actually ready:

docker run -d \
  --name myapp-db \
  --network myapp-net \
  --health-cmd="pg_isready -U app" \
  --health-interval=10s \
  --health-timeout=5s \
  --health-retries=5 \
  -e POSTGRES_USER=app \
  -e POSTGRES_PASSWORD=dbpass123 \
  postgres:16

Cleanup Script

A complete teardown script:

#!/bin/bash
docker stop myapp-web myapp-api myapp-cache myapp-db
docker rm myapp-web myapp-api myapp-cache myapp-db
docker network rm myapp-net
# Optionally remove volumes:
# docker volume rm myapp-pgdata

When to Migrate to Docker Compose

Use docker run scripts for:

  • Learning and experimentation
  • Simple two-container setups
  • CI/CD pipelines with custom orchestration

Switch to Docker Compose when:

  • You have 3+ containers that are regularly started together
  • You need dependency ordering and health check integration
  • Multiple team members need a reproducible setup
  • Environment variables are complex and environment-specific

Monitoring the Stack

# View all running containers
docker ps

# View resource usage
docker stats

# View logs from all containers
docker logs myapp-web
docker logs myapp-api
docker logs myapp-db
docker logs myapp-cache

Use Case

Setting up a complete local development stack with a web server, API, database, and cache, where all services communicate over an internal Docker network and data persists across restarts.

Try It — Docker Run Command Builder

Open full tool