A hands-on demonstration of Docker Compose networking concepts featuring multiple services with public and private endpoints, showcasing inter-service communication patterns and network isolation principles.
This playground helps you understand:
- Docker Compose multi-service architecture
- Network isolation and communication patterns
- Service discovery and inter-service communication
- Public vs private endpoint concepts
- Container orchestration best practices
graph TB
subgraph "Host System"
subgraph "Service 1"
S1PUB[Public Container<br/>service1<br/>Port: 8001:8080]
S1PRIV[Private Container<br/>service1-private<br/>No external port]
S1PUB --> S1PE[Public Endpoints<br/>/health<br/>/public/echo<br/>/call-others]
S1PRIV --> S1PV[Private Endpoint<br/>/private/info]
end
subgraph "Service 2"
S2PUB[Public Container<br/>service2<br/>Port: 8002:8080]
S2PRIV[Private Container<br/>service2-private<br/>No external port]
S2PUB --> S2PE[Public Endpoints<br/>/health<br/>/public/echo<br/>/call-others]
S2PRIV --> S2PV[Private Endpoint<br/>/private/info]
end
subgraph "Service 3"
S3PUB[Public Container<br/>service3<br/>Port: 8003:8080]
S3PRIV[Private Container<br/>service3-private<br/>No external port]
S3PUB --> S3PE[Public Endpoints<br/>/health<br/>/public/echo<br/>/call-others]
S3PRIV --> S3PV[Private Endpoint<br/>/private/info]
end
end
subgraph "External Access"
HOST[Host Machine<br/>localhost:8001-8003]
end
%% Public network connections shown through inter-service communication arrows
%% Inter-service communication (public only)
S1PE -.->|HTTP calls| S2PE
S1PE -.->|HTTP calls| S3PE
S2PE -.->|HTTP calls| S1PE
S2PE -.->|HTTP calls| S3PE
S3PE -.->|HTTP calls| S1PE
S3PE -.->|HTTP calls| S2PE
%% Same-service private connections (allowed)
S1PE -.->|Internal Access| S1PV
S2PE -.->|Internal Access| S2PV
S3PE -.->|Internal Access| S3PV
%% Host access
HOST -->|8001| S1PUB
HOST -->|8002| S2PUB
HOST -->|8003| S3PUB
%% Styling
classDef serviceBox fill:#b3e5fc,stroke:#0277bd,stroke-width:3px,color:#000000
classDef privateContainer fill:#ffeb3b,stroke:#f57f17,stroke-width:3px,color:#000000
classDef endpointBox fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px,color:#000000
classDef privateBox fill:#ffccbc,stroke:#d84315,stroke-width:2px,color:#000000
class S1PUB,S2PUB,S3PUB serviceBox
class S1PRIV,S2PRIV,S3PRIV privateContainer
class S1PE,S2PE,S3PE endpointBox
class S1PV,S2PV,S3PV privateBox
Note: The diagram shows only allowed connections. Cross-service private endpoints (e.g., service1 β service2-private) are blocked by network isolation and cannot communicate.
- Docker and Docker Compose installed
curl
andjq
(optional, for testing)
./start.sh
This will:
- Create Docker networks
- Build and start all services
- Verify services are healthy
- Display service endpoints
# Run comprehensive tests
./test.sh
# Or test manually
curl http://localhost:8001/health
curl http://localhost:8001/public/echo
curl http://localhost:8001/call-others | jq '.'
./stop.sh
# Or with cleanup
./stop.sh --clean
GET /health
- Health checkGET/POST /public/echo
- Echo service with request dataGET /call-others
- Test inter-service communication
GET /private/info
- Returns sensitive service information
curl http://localhost:8001/call-others
This endpoint demonstrates:
- How services discover and communicate with each other
- DNS resolution within Docker networks
- Success/failure patterns in distributed systems
- Same-service private access (β service1 β service1-private)
- Cross-service isolation (β service1 β service2-private)
The /private/info
endpoints demonstrate:
- True network isolation: Private containers are on separate networks
- Access control: Public containers return 404 for private endpoints
- Cross-service blocking: Private endpoints unreachable from other services
- Educational value: Shows real Docker network isolation in action
curl http://localhost:8001/health
curl http://localhost:8002/health
curl http://localhost:8003/health
All endpoints return consistent JSON format:
{
"service": "service1",
"endpoint": "/health",
"timestamp": "2024-01-01T12:00:00Z",
"data": {
"status": "healthy",
"ports": { "public": 8080, "private": 8081 }
}
}
# Test service health
curl http://localhost:8001/health
# Test public endpoints
curl http://localhost:8002/public/echo?message=hello
# Test inter-service communication
curl http://localhost:8003/call-others
# Test network isolation (should return 404)
curl http://localhost:8002/private/info
# POST request example
curl -X POST http://localhost:8001/public/echo \
-H "Content-Type: application/json" \
-d '{"test": "data"}'
# Run all tests
./test.sh
# View service logs (shows both public and private containers)
docker-compose -f docker-compose.service1.yml logs -f
.
βββ README.md # This file
βββ REQUIREMENTS.md # Detailed requirements
βββ CLAUDE.md # Development guidance
βββ docker-compose.networks.yml # Shared public network definition
βββ docker-compose.service1.yml # Service 1 configuration
βββ docker-compose.service2.yml # Service 2 configuration
βββ docker-compose.service3.yml # Service 3 configuration
βββ start.sh # Environment startup script
βββ stop.sh # Environment shutdown script
βββ test.sh # Automated testing script
βββ logs/ # Log files directory
βββ service[1-3]/ # Service implementation
βββ app.py # Flask application
βββ requirements.txt # Python dependencies
βββ Dockerfile # Container definition
- Create new service directory
- Copy and modify existing service files
- Create corresponding
docker-compose.serviceN.yml
- Update network configurations
- Test inter-service communication
Edit the Flask applications in service*/app.py
:
- Follow existing endpoint patterns
- Maintain consistent JSON response format
- Add appropriate logging
The current implementation demonstrates true network isolation:
- Shared public network: Defined in
docker-compose.networks.yml
(external) - Private networks: Each service creates its own private network
- Public containers: Connected to both
public_network
and their ownservice_private
- Private containers: Connected only to their service-specific private network
- APP_MODE environment variable: Controls endpoint availability per container
- Result: Private endpoints truly isolated at the network level
# All services (public and private containers)
docker-compose -f docker-compose.service1.yml logs
docker-compose -f docker-compose.service2.yml logs
docker-compose -f docker-compose.service3.yml logs
# Follow logs for specific service
docker-compose -f docker-compose.service1.yml logs -f
# View specific container logs
docker logs service1 # Public container
docker logs service1-private # Private container
# List networks
docker network ls
# Inspect public network
docker network inspect public_network
# View container networks
docker inspect service1 | grep NetworkMode
# Container status (should show 6 containers total)
docker ps
# Resource usage
docker stats
# Test network isolation
docker exec service1 python3 -c "import requests; requests.get('http://service2-private:8081/private/info')"
# Should fail with connection error
- Modify Response Format - Change the JSON structure and test compatibility
- Add Authentication - Implement token-based auth between services
- Implement Circuit Breaker - Add failure handling patterns
- Add Metrics - Integrate Prometheus metrics collection
- Database Integration - Add shared or dedicated databases
- Load Balancing - Scale services and add load balancers
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly with
./test.sh
- Submit a pull request
This project is open source and available under the MIT License.
# Check Docker status
docker info
# View build logs
docker-compose -f docker-compose.service1.yml up --build
# Clean and rebuild
./stop.sh --clean
./start.sh
# Reset networks
./stop.sh
docker network prune -f
./start.sh
Check if ports 8001-8003 are available:
lsof -i :8001
lsof -i :8002
lsof -i :8003
Happy Dockering! π³
For detailed implementation information, see REQUIREMENTS.md.