Docker Compose automatically creates a network for all services, enabling seamless service-to-service communication using container names as hostnames.
Default Network Behavior
When you run docker-compose up, Docker Compose:
- Creates a default bridge network named
{project}_default (e.g., src_default)
- Connects all services to this network
- Enables DNS-based service discovery using service names
- Isolates the application from other Docker networks
Inspecting the Network
# List all networks
docker network ls
# Inspect the application network
docker network inspect src_default
# View network configuration for a specific container
docker inspect catalogdb | grep -A 20 Networks
Service Discovery
Containers communicate using service names defined in docker-compose.yml. Docker’s built-in DNS server resolves these names to container IP addresses.
DNS Resolution Examples
# Basket API connecting to PostgreSQL
ConnectionStrings__Database=Server=basketdb;Port=5432;...
# Basket API connecting to Redis
ConnectionStrings__Redis=distributedcache:6379
# Basket API connecting to Discount gRPC
GrpcSettings__DiscountUrl=https://discount.grpc:8081
# Basket API connecting to RabbitMQ
MessageBroker__Host=amqp://ecommerce-mq:5672
# Shopping Web connecting to API Gateway
ApiSettings__GatewayAddress=http://yarpapigateway:8080
Hostname Resolution
Each service can be reached by:
- Service name:
catalogdb, basket.api, yarpapigateway
- Container name:
catalogdb, basketdb, distributedcache (when specified)
- Custom hostname:
ecommerce-mq (for RabbitMQ)
messagebroker:
container_name: messagebroker
hostname: ecommerce-mq # Custom hostname for RabbitMQ clustering
Network Architecture
Internal vs External Communication
Internal Communication (Container-to-Container)
Services communicate using internal container ports and service names:
# Basket API environment
GrpcSettings__DiscountUrl=https://discount.grpc:8081 # Port 8081 inside container
ConnectionStrings__Redis=distributedcache:6379 # Port 6379 inside container
External Communication (Host-to-Container)
External clients connect using published host ports:
shopping.web:
ports:
- "6005:8080" # Host:Container
Access from browser: http://localhost:6005
Port Mapping Strategy
All services expose both HTTP and HTTPS internally but map to unique host ports:
| Service | Internal Ports | External Ports | Access URL |
|---|
| catalog.api | 8080, 8081 | 6000, 6060 | http://localhost:6000 |
| basket.api | 8080, 8081 | 6001, 6061 | http://localhost:6001 |
| discount.grpc | 8080, 8081 | 6002, 6062 | http://localhost:6002 |
| ordering.api | 8080, 8081 | 6003, 6063 | http://localhost:6003 |
| yarpapigateway | 8080, 8081 | 6004, 6064 | http://localhost:6004 |
| shopping.web | 8080, 8081 | 6005, 6065 | http://localhost:6005 |
Containers always communicate using internal ports (8080/8081). External port mappings are only for host access.
Service Dependencies
The depends_on directive ensures proper startup order:
basket.api:
depends_on:
- basketdb
- distributedcache
- discount.grpc
- messagebroker
Dependency chain:
Databases & Infrastructure → APIs → Gateway → Web UI
catalogdb → catalog.api ┐
basketdb → basket.api ───┼→ yarpapigateway → shopping.web
orderdb → ordering.api ──┘
depends_on only controls startup order, not readiness. Services may start before dependencies are fully initialized. Implement retry logic in application code.
Network Isolation
By default, all services share one network. For better security, you can define multiple networks:
networks:
frontend:
backend:
database:
services:
shopping.web:
networks:
- frontend
yarpapigateway:
networks:
- frontend
- backend
catalog.api:
networks:
- backend
- database
catalogdb:
networks:
- database
This creates isolation:
- Web UI can only reach the gateway
- Gateway can reach APIs but not databases
- APIs can reach databases
Custom Network Configuration
Define Custom Network
networks:
aspnetrun:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
services:
catalog.api:
networks:
aspnetrun:
ipv4_address: 172.28.1.1
Connect to External Network
networks:
external_network:
external: true
services:
catalog.api:
networks:
- external_network
- default
Troubleshooting Network Issues
Test Service Connectivity
# Execute command in running container
docker exec -it basketapi bash
# Test DNS resolution
ping catalogdb
ping discount.grpc
# Test port connectivity
telnet catalogdb 5432
nc -zv distributedcache 6379
# Check HTTP endpoints
curl http://catalog.api:8080/health
curl http://discount.grpc:8080/health
Verify Network Configuration
# List networks
docker network ls
# Inspect network
docker network inspect src_default
# Check container network settings
docker inspect catalog.api --format='{{json .NetworkSettings.Networks}}' | jq
Common Issues
Cannot Resolve Service Name
# Check if services are on same network
docker network inspect src_default
# Verify service name matches docker-compose.yml
docker-compose ps
Connection Refused
# Check if target service is running
docker-compose ps
# Check if target port is listening
docker exec catalogdb netstat -tlnp | grep 5432
# View service logs
docker-compose logs catalogdb
Wrong Port Number
Remember to use internal container ports, not host-mapped ports:
# ❌ Wrong - using host port
ConnectionStrings__Database=Server=catalogdb;Port=5432;...
# ✅ Correct - using container port
ConnectionStrings__Database=Server=catalogdb;Port=5432;...
For basketdb accessed from host:
# ❌ Wrong
psql -h localhost -p 5432 -U postgres
# ✅ Correct (basketdb maps 5433:5432)
psql -h localhost -p 5433 -U postgres
Bridge Network Overhead
Docker bridge networks have minimal overhead (typically less than 1% latency):
# Test latency between containers
docker exec basket.api ping -c 10 catalogdb
Optimize DNS Caching
Enable DNS caching in .NET services:
services.Configure<SocketsHttpHandler>(options =>
{
options.PooledConnectionLifetime = TimeSpan.FromMinutes(15);
});
Host Network Mode
For maximum performance (Linux only), use host networking:
services:
catalog.api:
network_mode: "host"
Host networking disables network isolation and requires manual port management. Not recommended for multi-service applications.
Production Networking
For production deployments:
Use Overlay Networks (Docker Swarm/Kubernetes)
networks:
aspnetrun:
driver: overlay
attachable: true
Enable SSL/TLS Between Services
basket.api:
environment:
- GrpcSettings__DiscountUrl=https://discount.grpc:8081
- GRPC_SSL_CIPHER_SUITES=ECDHE-RSA-AES128-GCM-SHA256
Implement Service Mesh
Consider using service mesh solutions:
- Istio
- Linkerd
- Consul Connect
These provide:
- mTLS encryption
- Advanced traffic routing
- Observability
- Circuit breaking
- Rate limiting
Network Security Best Practices
- Minimize exposed ports: Only publish ports that need external access
- Use internal networks: Don’t expose databases to host
- Enable encryption: Use TLS for inter-service communication
- Implement network policies: Restrict traffic between services
- Monitor network traffic: Use tools like Wireshark or tcpdump
- Scan for vulnerabilities: Regularly audit network configuration
# Example: Restrict database access
catalogdb:
# Remove port mapping in production
# ports:
# - "5432:5432"
networks:
- database # Only accessible on database network