Category: python
Introduction to Python Microservices with Docker Compose
Published on 22 Aug 2026
Explanation
Docker Compose allows multiple containers to be defined and managed using a single YAML configuration file. In a Python microservices application, each service can run in its own container. For example, a Product Service and Order Service can be developed independently while Docker Compose manages their networking, ports, environment variables, and startup. This makes it easier to run an entire microservices application locally.
Code:
services:
product-service:
build: ./product-service
ports:
- '8001:8000'
order-service:
build: ./order-service
ports:
- '8002:8000'
# Start all services:
# docker compose up --build
Explanation
Each Python microservice should have its own application code, dependencies, and Dockerfile. The Product Service can expose REST endpoints using FastAPI. Its Dockerfile creates an isolated environment containing Python, the required packages, and the application code. Docker Compose can then build and start this service automatically.
Code:
# product-service/app/main.py
from fastapi import FastAPI
app = FastAPI(title='Product Service')
@app.get('/products')
def get_products():
return [
{'id': 1, 'name': 'Laptop', 'price': 65000},
{'id': 2, 'name': 'Mouse', 'price': 750}
]
# product-service/requirements.txt
# fastapi
# uvicorn
# product-service/Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app ./app
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Explanation
The Order Service can run in a separate container from the Product Service. It can communicate with the Product Service using its Docker Compose service name. Inside a Docker network, containers should not use localhost to communicate with each other because localhost refers to the current container. Docker Compose provides DNS-based service discovery, allowing the Order Service to call Product Service using a URL such as http://product-service:8000.
Code:
# order-service/app/main.py
from fastapi import FastAPI
import httpx
import os
app = FastAPI(title='Order Service')
PRODUCT_SERVICE_URL = os.getenv(
'PRODUCT_SERVICE_URL',
'http://product-service:8000'
)
@app.get('/orders/{product_id}')
async def create_order(product_id: int):
async with httpx.AsyncClient() as client:
response = await client.get(
f'{PRODUCT_SERVICE_URL}/products',
timeout=5.0
)
products = response.json()
return {
'product_id': product_id,
'products': products,
'message': 'Order service received product data'
}
Explanation
Docker Compose automatically creates a network for services defined in the Compose file. Services can communicate with each other using their service names. In this example, the Order Service uses product-service as the hostname instead of localhost. This allows the same Compose configuration to work even though containers may receive different IP addresses when they are recreated.
Code:
services:
product-service:
build: ./product-service
ports:
- '8001:8000'
order-service:
build: ./order-service
ports:
- '8002:8000'
environment:
PRODUCT_SERVICE_URL: http://product-service:8000
depends_on:
- product-service
# Communication:
#
# Browser
# |
# +--> localhost:8001 -> Product Service
# |
# +--> localhost:8002 -> Order Service
# |
# v
# product-service:8000
# |
# v
# Product Service
Explanation
Once the Dockerfiles and Compose configuration are created, the complete microservices application can be started using Docker Compose. The docker compose up --build command builds the images and starts the containers. docker compose ps shows the running services, while docker compose logs can be used to inspect application logs. The application can then be tested through the exposed FastAPI endpoints and Swagger documentation.
Code:
# Build and start all services docker compose up --build # Run in background docker compose up -d --build # Check services docker compose ps # View logs docker compose logs # View only Order Service logs docker compose logs order-service # Stop services docker compose down # APIs: # Product Service -> http://localhost:8001/docs # Order Service -> http://localhost:8002/docs