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.
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:
- Database (no dependencies)
- Cache (no dependencies)
- API (depends on database and cache)
- 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.