Building apps today often means using more than just one service — like databases, APIs, cache servers, and reverse proxies. Managing all these manually can be messy.
That’s where Docker Compose comes in! It helps you run multiple services together in a simple, organized way.
In this guide, we’ll show you how to create a sample docker-compose.yml
file with:
- A PostgreSQL database
- Two .NET API servers (for simulating microservices)
- A Redis cache
- An NGINX reverse proxy
By the end, you’ll know how to use Docker Compose to build real-world applications!
What is Docker Compose?
Docker Compose lets you define and run multiple Docker containers easily using just one YAML file. With a single command, you can start, stop, and manage your entire application stack — no more running each service by hand!
Why Use Docker Compose?
- One command to manage everything:
docker-compose up
- Easy to share: Same setup works on any machine
- Automatic networking: Services can talk to each other without extra setup
- Scale easily: Add more instances of services when needed
Let’s Build Your First Docker Compose Setup!
We’ll create a docker-compose.yml
file to set up:
- PostgreSQL database for storing data
- Two .NET API servers that connect to the database
- Redis for caching
- NGINX for routing web traffic
Here’s the complete file, then we’ll explain it piece by piece.
version: "3.9" services: db: image: postgres:15.2 container_name: database_container restart: always environment: POSTGRES_USER: myuser POSTGRES_PASSWORD: mypassword POSTGRES_DB: mydatabase ports: - "5432:5432" volumes: - db_data:/var/lib/postgresql/data api_server_1: image: mydotnetapi:latest container_name: api_server_1 depends_on: - db ports: - "5001:80" environment: DB_CONNECTION_STRING: Host=db;Port=5432;Username=myuser;Password=mypassword;Database=mydatabase networks: - app_network api_server_2: image: mydotnetapi:latest container_name: api_server_2 depends_on: - db ports: - "5002:80" environment: DB_CONNECTION_STRING: Host=db;Port=5432;Username=myuser;Password=mypassword;Database=mydatabase networks: - app_network redis: image: redis:7.0 container_name: redis_cache ports: - "6379:6379" networks: - app_network nginx: image: nginx:latest container_name: nginx_proxy ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - api_server_1 - api_server_2 networks: - app_network volumes: db_data: networks: app_network:
Quick Breakdown
1. Specify the Docker Compose Version
version: "3.9"
This tells Docker Compose which file format you’re using (always use the latest stable version).
2. Set Up the Database
db: image: postgres:15.2 ...
- Runs a PostgreSQL database
- Saves data even if the container restarts
- Opens port 5432 so you can connect to it
3. Set Up the API Servers
api_server_1: image: mydotnetapi:latest ...
- Two API servers are created (on ports 5001 and 5002)
- Each connects to the database using environment variables
- Helps simulate a microservices setup
4. Add Redis Cache
redis: image: redis:7.0 ...
- Fast in-memory storage
- Great for caching data and improving app performance
5. Configure the NGINX Reverse Proxy
nginx: image: nginx:latest ...
- Routes incoming web traffic
- For example:
- Requests to
/api1
go to API Server 1 - Requests to
/api2
go to API Server 2 - You’ll set routing rules inside a simple
nginx.conf
file
6. Define Volumes and Networks
volumes: db_data: networks: app_network:
- Volumes keep your database data safe
- Networks let containers talk to each other without exposing extra ports
How to Run Everything
- Save the
docker-compose.yml
file in your project folder. - Open your terminal and run:
docker-compose up --build
- Visit
http://localhost
to see NGINX working. - Access your APIs:
http://localhost/api1
http://localhost/api2
Final Thoughts
Congratulations! 🎉 You’ve built a basic multi-service app using Docker Compose.
This is a stepping stone to mastering bigger tools like Kubernetes.