Skip to main content
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:
  1. Creates a default bridge network named {project}_default (e.g., src_default)
  2. Connects all services to this network
  3. Enables DNS-based service discovery using service names
  4. 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:
ServiceInternal PortsExternal PortsAccess URL
catalog.api8080, 80816000, 6060http://localhost:6000
basket.api8080, 80816001, 6061http://localhost:6001
discount.grpc8080, 80816002, 6062http://localhost:6002
ordering.api8080, 80816003, 6063http://localhost:6003
yarpapigateway8080, 80816004, 6064http://localhost:6004
shopping.web8080, 80816005, 6065http://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

Network Performance

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

  1. Minimize exposed ports: Only publish ports that need external access
  2. Use internal networks: Don’t expose databases to host
  3. Enable encryption: Use TLS for inter-service communication
  4. Implement network policies: Restrict traffic between services
  5. Monitor network traffic: Use tools like Wireshark or tcpdump
  6. 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

Build docs developers (and LLMs) love