Cloud & DevOps · PRACTICAL GUIDE

Run Multi-Container Applications with Docker Compose

Define and run a frontend, backend, database and AI service as one connected application using a readable Docker Compose configuration.

HANDBOOK JOURNEYByte 4 of 5View all Bytes
HANDBOOK JOURNEYByte 4 of 5

Cloud & DevOps

21 min focused reading
  1. BYTE 01What Is Docker?
  2. BYTE 02Dockerize Your First Python Application
  3. BYTE 03Docker Essentials
  4. 05BYTE 05Dockerize and Deploy a Generative AI Application
FAMILIAR SCENARIO

A restaurant works through specialised counters

Order desk, kitchen, billing and inventory perform different jobs but use one operating plan and communicate by known names.

01Compose plan
02Services
03Network
04Shared state

Connect the idea: Compose coordinates multiple specialised containers as one application.

Quick Start

DOCKER HANDBOOK 04

What you will build mentally

A four-service application model: browser-facing frontend, backend API, PostgreSQL database and internal AI service. You will learn service discovery, startup dependencies, health checks, volumes and configuration boundaries.

Start from Basics

Real applications rarely run as one container. A frontend may call a backend, the backend may use a database and an AI service may handle model-specific work. Starting each container with a long docker run command is difficult to reproduce and review.

Docker Compose lets you declare the application in compose.yaml. The file describes services, images or build contexts, networks, volumes, ports, health checks and runtime configuration. docker compose up reconciles that definition into running containers.

Core Explanation

CONCEPT LAB 04

Connect a small application team

Select a service to see whom it calls. Inside Compose, service names act like contact names.

Calls backend:8000

The browser-facing screen sends work to the backend service.

GUIDED COMMAND SIMULATIONRun a command and watch what Docker creates
LEARNING MODE
SIMULATED TERMINAL
$ docker compose up --build

Click execute — no real system changes are made

DOCKER OUTPUTWAITING

The created object will appear here

Browser learning simulation — this does not execute on your computer.
QUICK PREDICTIONFrom the backend container, should the database address be localhost?

Architecture / Flow Diagram

VISUAL EXPLAINERONE APPLICATION, MULTIPLE SERVICES
DOCKER
FrontendUser interface
BackendApplication API
DatabaseDurable state
AI serviceModel workflow
Compose defines services, networks, volumes and configuration as one repeatable application model.
COMPOSE ARCHITECTUREOne command starts one connected application
FOLLOW THE FLOW
01
compose.yamlSystem definition
02
ServicesSeparate jobs
03
Compose networkService names connect
04
Named volumeDurable state
Remember: Compose coordinates containers; it does not merge them into one container.
TEXT
01Browser02  ↓ localhost:300003Frontend container04  ↓ http://backend:800005Backend container ─────→ AI service:900006  ↓ postgres:543207Database container08  ↓09Named volume

Only the frontend must be public in this simple architecture. The backend can be published during local development, but internal services can communicate on the Compose network by service name.

Types / Components

Read a practical compose.yaml

YAML
01services:02  frontend:03    build: ./frontend04    ports:05      - "3000:3000"06    environment:07      API_BASE_URL: http://backend:800008    depends_on:09      backend:10        condition: service_healthy1112  backend:13    build: ./backend14    environment:15      DATABASE_URL: postgresql://app:app@postgres:5432/app16      AI_SERVICE_URL: http://ai-service:900017    depends_on:18      postgres:19        condition: service_healthy20      ai-service:21        condition: service_started22    healthcheck:23      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]24      interval: 10s25      timeout: 3s26      retries: 52728  postgres:29    image: postgres:1730    environment:31      POSTGRES_USER: app32      POSTGRES_PASSWORD: app33      POSTGRES_DB: app34    volumes:35      - postgres-data:/var/lib/postgresql/data36    healthcheck:37      test: ["CMD-SHELL", "pg_isready -U app"]38      interval: 10s39      timeout: 5s40      retries: 54142  ai-service:43    build: ./ai-service44    environment:45      MODEL_NAME: local-demo-model4647volumes:48  postgres-data:

This is a learning configuration, not a production-ready security policy. Never use the example database password in a real environment.

The most important networking rule

Inside the frontend container, localhost means the frontend container itself. It does not mean the backend container. Compose service discovery lets the frontend reach http://backend:8000 and the backend reach postgres:5432.

This single idea solves many beginner connection failures.

TAMIL LEARNER SUPPORT

Simple Tanglish — localhost rule

Container-க்குள் localhost என்றால் அந்த same container. Backend database-ஐ call பண்ணும்போது localhost:5432 use பண்ணக்கூடாது. Compose service name use பண்ணணும்: postgres:5432.

depends_on is not business readiness

Starting a database process does not mean it is ready to accept queries. A health check can give Compose a stronger readiness signal, and depends_on can wait for that condition. Your application should still handle temporary unavailability with bounded retries and clear errors because services can fail after startup.

Operate the stack

BASH
01docker compose up --build02docker compose ps03docker compose logs -f backend04docker compose exec backend sh05docker compose down

Use docker compose down -v only when you intentionally want to remove named volumes declared by the project. That can delete database data and should not be a casual cleanup command.

Docker Run vs Docker Compose

DecisionSeparate docker run commandsDocker Compose
Application definitionSpread across commandsRecorded in compose.yaml
Service communicationNetwork and names configured manuallyService names available on the project network
Team repeatabilityEasy to miss one optionOne shared definition
Best fitOne quick containerConnected local application stack

Real-World Examples

BEFORE → ACTION → AFTERRead each story from the failed setup to the result the team can see.
API and database
Before Docker
The API tries localhost and cannot find the database container.
Team action
Use the Compose service address postgres:5432.
After Docker
The API reaches the database by service name.
SETUP MATCHED
Starting the stack
Before Docker
Four separate docker run commands are easy to mistype.
Team action
Record the services in compose.yaml and run docker compose up.
After Docker
The application team starts from one definition.
SETUP MATCHED
Database replacement
Before Docker
The database container is recreated during development.
Team action
Attach a named volume in the Compose file.
After Docker
The replacement service keeps the selected data.
SETUP MATCHED
Docker does not fix application bugs. In these examples, it removes uncertainty about the Python version, libraries and selected release package.

Imagine Pannunga

SEE IT IN PRACTICE

One customer experience, several specialised stations

A restaurant is one customer experience but contains a host desk, kitchen, pantry and billing station. Each has a separate responsibility and communicates through known handoffs. A manager does not combine every role into one person merely to simplify the floor plan.

Compose is the operating plan: which stations exist, how they are reached, what supplies persist and which station must be ready first. The analogy stops at runtime resilience—software services still need timeouts, retries, monitoring and failure isolation.

Use Cases

WHO USES THIS — AND WHY?Choose the person first; the Docker benefit becomes clearer.
Developer

“How do I start the full app locally?”

Run docker compose up
QA engineer

“Can I reproduce the connected stack?”

Use the committed Compose definition
DevOps engineer

“Which services are public or internal?”

Review ports, networks and secrets
SRE engineer

“Which service is unhealthy?”

Inspect service state and focused logs
Docker is useful when the learner needs the same prepared application setup in another place.

Key Takeaways

  1. Compose records a multi-container application in one file.
  2. Each service should have one clear responsibility.
  3. Service names provide addresses inside the Compose network.
  4. localhost always refers to the current container.
  5. Publish only services that need host access.
  6. A started service may not yet be ready.
  7. Named volumes keep selected state outside one container.
  8. Focused logs identify which service failed first.

Final Thought + Next Path

Think of Compose as the operating plan for a small application team: it names each service, records how they connect and starts them from one definition. In Byte 05, you will take the packaged application toward deployment with versioned images, runtime secrets, health checks and rollback.

FAQ + Knowledge Check

LESSON CHECKPOINTConfirm the concept before moving forward

Choose an answer, inspect the explanation and explain the idea in your own words.

RETENTION

Why cannot the backend use localhost for PostgreSQL? Because localhost points back to the backend container. Use the service name postgres.

Does depends_on prove that the database is ready? No. It helps with order; readiness needs a health signal and resilient application behaviour.

Knowledge check: Which command starts the defined stack? docker compose up. Which command shows service states? docker compose ps.

Learning rule: explain the answer in your own words before checking the next Byte.

A disciplined debugging sequence

  1. Run docker compose config to inspect the resolved configuration.
  2. Run docker compose ps to check service and health states.
  3. Read logs for the service receiving the failed request.
  4. Confirm it uses service names, not localhost, for container-to-container calls.
  5. Test connectivity from the calling container.
  6. Check configuration, credentials and database migrations.

Do not restart every service immediately; restarts can hide the first useful failure evidence.

Common mistakes

AVOID THESE

Common mistakes

  • Using localhost to call another container.
  • Publishing every internal service port to the host.
  • Assuming startup order guarantees application readiness.
  • Storing production passwords directly in compose.yaml.
  • Running stateful databases without a volume and backup strategy.
  • Treating local Compose as a complete production orchestration design.

Interview answer

CAREER

How do services communicate in Docker Compose?

Strong answer: Compose creates a default network for the application, and services can reach one another using service names as DNS names. Internal traffic uses the container port, while published ports are for access through the host. I use health checks and application-level retry behaviour instead of assuming a started container is ready.

Official references

OPTIONAL LEARNING CONNECTIONS

Continue by concept

Choose only what supports your next goal. This Byte does not require either link.