docker-compose-networking

Use when configuring networks and service communication in Docker Compose including bridge networks, overlay networks, service discovery, and inter-service communication.

16 stars

Best use case

docker-compose-networking is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Use when configuring networks and service communication in Docker Compose including bridge networks, overlay networks, service discovery, and inter-service communication.

Teams using docker-compose-networking should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/docker-compose-networking/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/development/docker-compose-networking/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/docker-compose-networking/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How docker-compose-networking Compares

Feature / Agentdocker-compose-networkingStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Use when configuring networks and service communication in Docker Compose including bridge networks, overlay networks, service discovery, and inter-service communication.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Docker Compose Networking

Master network configuration and service communication patterns in Docker Compose for building secure, scalable multi-container applications.

## Default Bridge Network

Docker Compose automatically creates a default bridge network for all services in a compose file:

```yaml
version: '3.8'

services:
  frontend:
    image: nginx:alpine
    ports:
      - "80:80"
    # Can reach backend using service name as hostname

  backend:
    image: node:18-alpine
    command: node server.js
    # Accessible at hostname 'backend' from frontend

  database:
    image: postgres:15-alpine
    environment:
      POSTGRES_PASSWORD: secret
    # Accessible at hostname 'database' from backend
```

In this setup:

- All services can communicate using service names as hostnames
- Frontend can reach backend at `http://backend:3000`
- Backend can reach database at `postgres://database:5432`
- Only frontend's port 80 is exposed to host

## Custom Bridge Networks

Define custom networks for service isolation and segmentation:

```yaml
version: '3.8'

services:
  frontend:
    image: nginx:alpine
    networks:
      - frontend-network
    ports:
      - "80:80"

  api:
    image: node:18-alpine
    networks:
      - frontend-network
      - backend-network
    environment:
      DATABASE_URL: postgresql://db:5432/app

  database:
    image: postgres:15-alpine
    networks:
      - backend-network
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: app
    volumes:
      - db-data:/var/lib/postgresql/data

  cache:
    image: redis:7-alpine
    networks:
      - backend-network
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data

networks:
  frontend-network:
    driver: bridge
  backend-network:
    driver: bridge
    internal: true

volumes:
  db-data:
  redis-data:
```

Network isolation:

- Frontend can only reach API
- Frontend cannot reach database or cache directly
- API can reach all services
- Backend network is internal (no external access)

## Network Aliases

Configure multiple hostnames for service discovery:

```yaml
version: '3.8'

services:
  web:
    image: nginx:alpine
    networks:
      public:
        aliases:
          - website
          - www
          - web-server
      internal:
        aliases:
          - web-internal

  api:
    image: node:18-alpine
    networks:
      public:
        aliases:
          - api-server
          - backend
      internal:
        aliases:
          - api-internal
    depends_on:
      - database

  database:
    image: postgres:15-alpine
    networks:
      internal:
        aliases:
          - db
          - postgres
          - primary-db
    environment:
      POSTGRES_PASSWORD: secret

networks:
  public:
    driver: bridge
  internal:
    driver: bridge
    internal: true
```

Services can be reached by any of their aliases:

- `http://website`, `http://www`, `http://web-server` all reach web service
- `postgresql://db:5432`, `postgresql://postgres:5432` both reach database

## Static IP Addresses

Assign fixed IP addresses for services requiring stable networking:

```yaml
version: '3.8'

services:
  loadbalancer:
    image: nginx:alpine
    networks:
      app-network:
        ipv4_address: 172.28.1.10
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro

  app-1:
    image: myapp:latest
    networks:
      app-network:
        ipv4_address: 172.28.1.11
    environment:
      APP_ID: "1"

  app-2:
    image: myapp:latest
    networks:
      app-network:
        ipv4_address: 172.28.1.12
    environment:
      APP_ID: "2"

  app-3:
    image: myapp:latest
    networks:
      app-network:
        ipv4_address: 172.28.1.13
    environment:
      APP_ID: "3"

  database:
    image: postgres:15-alpine
    networks:
      app-network:
        ipv4_address: 172.28.1.20
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

networks:
  app-network:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16
          gateway: 172.28.1.1

volumes:
  pgdata:
```

## External Networks

Connect to existing Docker networks created outside Compose:

```yaml
version: '3.8'

services:
  api:
    image: node:18-alpine
    networks:
      - app-network
      - shared-network
    environment:
      DATABASE_URL: postgresql://db:5432/app

  database:
    image: postgres:15-alpine
    networks:
      - app-network
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

networks:
  app-network:
    driver: bridge

  shared-network:
    external: true
    name: company-shared-network

volumes:
  pgdata:
```

Create external network first:

```bash
docker network create company-shared-network
docker compose up -d
```

## Host Network Mode

Use host networking for maximum performance (Linux only):

```yaml
version: '3.8'

services:
  high-performance-app:
    image: myapp:latest
    network_mode: "host"
    environment:
      BIND_ADDRESS: "0.0.0.0"
      PORT: "8080"
    # No port mapping needed - directly uses host's network stack

  monitoring:
    image: prometheus:latest
    network_mode: "host"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.listen-address=0.0.0.0:9090'

volumes:
  prometheus-data:
```

Note: Host networking bypasses Docker network isolation and is typically used for monitoring tools or high-throughput applications.

## Service Discovery and DNS

Configure DNS resolution and service discovery:

```yaml
version: '3.8'

services:
  api:
    image: node:18-alpine
    networks:
      - app-network
    dns:
      - 8.8.8.8
      - 8.8.4.4
    dns_search:
      - company.local
    extra_hosts:
      - "legacy-api.company.local:192.168.1.100"
      - "auth-service.company.local:192.168.1.101"
    environment:
      DATABASE_HOST: database.company.local

  database:
    image: postgres:15-alpine
    networks:
      app-network:
        aliases:
          - database.company.local
          - db.company.local
    hostname: primary-database
    domainname: company.local
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

networks:
  app-network:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: br-company-app

volumes:
  pgdata:
```

## Link Containers (Legacy)

While `links` is deprecated, understanding it helps migrate legacy configurations:

```yaml
version: '3.8'

services:
  # Modern approach - use networks instead
  web:
    image: nginx:alpine
    networks:
      - app-network
    depends_on:
      - api

  api:
    image: node:18-alpine
    networks:
      - app-network
    depends_on:
      - database
    environment:
      # Use service name as hostname
      DATABASE_URL: postgresql://database:5432/app

  database:
    image: postgres:15-alpine
    networks:
      - app-network
    environment:
      POSTGRES_PASSWORD: secret

networks:
  app-network:
    driver: bridge
```

## Multi-Network Architecture

Complex applications with multiple isolated networks:

```yaml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    networks:
      - public
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - frontend
      - api

  frontend:
    image: react-app:latest
    networks:
      - public
      - frontend-tier
    environment:
      API_URL: http://api:3000

  api:
    image: node-api:latest
    networks:
      - frontend-tier
      - backend-tier
    environment:
      DATABASE_URL: postgresql://postgres:5432/app
      REDIS_URL: redis://cache:6379
      QUEUE_URL: amqp://rabbitmq:5672
    depends_on:
      - database
      - cache
      - queue

  worker:
    image: node-worker:latest
    networks:
      - backend-tier
    environment:
      DATABASE_URL: postgresql://postgres:5432/app
      QUEUE_URL: amqp://rabbitmq:5672
    depends_on:
      - database
      - queue
    deploy:
      replicas: 3

  database:
    image: postgres:15-alpine
    networks:
      - backend-tier
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: app
    volumes:
      - pgdata:/var/lib/postgresql/data

  cache:
    image: redis:7-alpine
    networks:
      - backend-tier
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data

  queue:
    image: rabbitmq:3-management-alpine
    networks:
      - backend-tier
      - management
    ports:
      - "15672:15672"  # Management UI
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: secret
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq

  monitoring:
    image: prometheus:latest
    networks:
      - management
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus

networks:
  public:
    driver: bridge
  frontend-tier:
    driver: bridge
    internal: true
  backend-tier:
    driver: bridge
    internal: true
  management:
    driver: bridge

volumes:
  pgdata:
  redis-data:
  rabbitmq-data:
  prometheus-data:
```

Network segmentation:

- Public: Internet-facing services (nginx, frontend)
- Frontend-tier: Frontend and API communication
- Backend-tier: API, workers, databases, cache, queue
- Management: Monitoring and administration tools

## Port Publishing Strategies

Control how services expose ports:

```yaml
version: '3.8'

services:
  # Short syntax - host:container
  web:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    networks:
      - public

  # Long syntax with protocol specification
  api:
    image: node:18-alpine
    ports:
      - target: 3000
        published: 3000
        protocol: tcp
        mode: host
    networks:
      - app-network

  # Random host port
  app:
    image: myapp:latest
    ports:
      - "3000"  # Docker assigns random host port
    networks:
      - app-network

  # Bind to specific host interface
  admin:
    image: admin-panel:latest
    ports:
      - "127.0.0.1:8080:80"  # Only accessible from localhost
    networks:
      - admin-network

  # UDP protocol
  dns:
    image: bind9:latest
    ports:
      - "53:53/udp"
      - "53:53/tcp"
    networks:
      - dns-network

  # Range of ports
  streaming:
    image: rtmp-server:latest
    ports:
      - "1935:1935"
      - "8080-8089:8080-8089"
    networks:
      - streaming-network

networks:
  public:
  app-network:
  admin-network:
    internal: true
  dns-network:
  streaming-network:
```

## Container Communication Patterns

### Request-Response Pattern

```yaml
version: '3.8'

services:
  gateway:
    image: nginx:alpine
    networks:
      - frontend
    ports:
      - "80:80"
    volumes:
      - ./nginx-gateway.conf:/etc/nginx/nginx.conf:ro

  service-a:
    image: service-a:latest
    networks:
      - frontend
      - backend
    environment:
      SERVICE_B_URL: http://service-b:8080
      DATABASE_URL: postgresql://db:5432/service_a

  service-b:
    image: service-b:latest
    networks:
      - frontend
      - backend
    environment:
      DATABASE_URL: postgresql://db:5432/service_b

  database:
    image: postgres:15-alpine
    networks:
      - backend
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true

volumes:
  pgdata:
```

### Pub-Sub Pattern

```yaml
version: '3.8'

services:
  publisher:
    image: publisher:latest
    networks:
      - messaging
    environment:
      REDIS_URL: redis://redis:6379
    depends_on:
      - redis

  subscriber-1:
    image: subscriber:latest
    networks:
      - messaging
    environment:
      REDIS_URL: redis://redis:6379
      SUBSCRIBER_ID: "1"
    depends_on:
      - redis

  subscriber-2:
    image: subscriber:latest
    networks:
      - messaging
    environment:
      REDIS_URL: redis://redis:6379
      SUBSCRIBER_ID: "2"
    depends_on:
      - redis

  redis:
    image: redis:7-alpine
    networks:
      - messaging
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data

networks:
  messaging:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.enable_icc: "true"

volumes:
  redis-data:
```

## Network Troubleshooting Configuration

Enable debugging and monitoring:

```yaml
version: '3.8'

services:
  app:
    image: myapp:latest
    networks:
      app-network:
        aliases:
          - primary-app
    cap_add:
      - NET_ADMIN
      - NET_RAW

  debug:
    image: nicolaka/netshoot:latest
    networks:
      - app-network
    command: sleep infinity
    cap_add:
      - NET_ADMIN
      - NET_RAW
    stdin_open: true
    tty: true

  database:
    image: postgres:15-alpine
    networks:
      app-network:
        aliases:
          - db
    environment:
      POSTGRES_PASSWORD: secret

networks:
  app-network:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.enable_ip_masquerade: "true"
      com.docker.network.driver.mtu: "1500"
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16
```

Debug commands:

```bash
# Enter debug container
docker compose exec debug bash

# Test connectivity
ping app
curl http://app:8080/health

# Check DNS resolution
nslookup app
dig app

# Network scanning
nmap -p- app

# Trace route
traceroute app

# Monitor traffic
tcpdump -i eth0 -n
```

## IPv6 Networking

Enable IPv6 support:

```yaml
version: '3.8'

services:
  web:
    image: nginx:alpine
    networks:
      - ipv6-network
    ports:
      - "80:80"

  api:
    image: node:18-alpine
    networks:
      ipv6-network:
        ipv6_address: 2001:db8:1::10

  database:
    image: postgres:15-alpine
    networks:
      ipv6-network:
        ipv6_address: 2001:db8:1::20
    environment:
      POSTGRES_PASSWORD: secret

networks:
  ipv6-network:
    driver: bridge
    enable_ipv6: true
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16
        - subnet: 2001:db8:1::/64
```

## When to Use This Skill

Use docker-compose-networking when you need to:

- Configure custom network topologies for multi-container applications
- Implement network segmentation and service isolation
- Set up service discovery and inter-service communication
- Design secure network architectures with frontend/backend separation
- Configure static IP addresses for services
- Connect to external Docker networks
- Implement complex microservices communication patterns
- Troubleshoot network connectivity issues
- Configure DNS resolution and hostname aliases
- Set up pub-sub or message queue architectures
- Enable IPv6 networking
- Optimize network performance with host networking
- Configure port publishing and exposure strategies

## Best Practices

1. **Use Custom Networks for Isolation**: Always create custom networks instead of relying solely on the default network for better security and organization.

2. **Implement Network Segmentation**: Separate frontend, backend, and data tiers into different networks to limit attack surface.

3. **Use Internal Networks**: Mark backend networks as `internal: true` to prevent external access to sensitive services like databases.

4. **Prefer Service Names Over IPs**: Use Docker's built-in DNS and service names instead of hardcoding IP addresses for maintainability.

5. **Configure Health Checks**: Implement health checks to ensure services are ready before routing traffic to them.

6. **Use Network Aliases**: Define meaningful aliases for services to support multiple naming conventions and easier migration.

7. **Avoid Host Networking Unless Necessary**: Use bridge networks by default; host networking should only be used for specific performance requirements.

8. **Document Network Architecture**: Clearly comment your network design and document which services can communicate with each other.

9. **Use Depends_on Wisely**: Combine `depends_on` with health checks to ensure services start in the correct order.

10. **Implement Least Privilege**: Only expose ports that absolutely need to be accessible from outside the Docker network.

11. **Use Environment Variables for URLs**: Configure service endpoints through environment variables for flexibility across environments.

12. **Test Network Isolation**: Regularly verify that services can only communicate through intended network paths.

13. **Configure Appropriate MTU**: Set MTU values based on your network infrastructure to avoid fragmentation issues.

14. **Use External Networks for Shared Resources**: When multiple Compose projects need to communicate, use external networks rather than duplicating services.

15. **Monitor Network Performance**: Use tools like `docker stats` and dedicated monitoring containers to track network usage and identify bottlenecks.

## Common Pitfalls

1. **Exposing All Services Publicly**: Don't publish ports for services that should only be accessed internally; use networks instead of port publishing.

2. **Hardcoding IP Addresses**: Avoid static IP addresses unless absolutely necessary; rely on service discovery instead.

3. **Using Default Network Only**: Not creating custom networks misses opportunities for proper segmentation and isolation.

4. **Ignoring Network Modes**: Using the wrong network mode (bridge vs host vs overlay) for your use case can cause connectivity or performance issues.

5. **Missing Network Dependencies**: Not properly configuring `depends_on` can cause services to fail when trying to connect to unavailable services.

6. **Overusing Host Networking**: Using `network_mode: host` unnecessarily breaks container isolation and portability.

7. **Not Using Internal Networks**: Failing to mark backend networks as internal leaves databases and sensitive services exposed.

8. **Mixing Network Modes**: Trying to publish ports or connect to networks when using `network_mode: host` causes configuration errors.

9. **Circular Network Dependencies**: Creating network dependencies that form a circle prevents containers from starting properly.

10. **Ignoring DNS Configuration**: Not configuring DNS properly can cause name resolution failures in containerized applications.

11. **Subnet Conflicts**: Using IP ranges that conflict with host or other Docker networks causes routing issues.

12. **Not Testing Network Policies**: Assuming network isolation works without testing can leave security vulnerabilities.

13. **Exposing Management Interfaces**: Publishing management ports (like RabbitMQ, Redis, PostgreSQL) without authentication or IP restrictions.

14. **Using Links Instead of Networks**: The deprecated `links` feature should be replaced with modern network configuration.

15. **Ignoring Network Driver Options**: Not configuring driver options like MTU or IP masquerade can cause subtle connectivity problems in production.

## Resources

### Official Documentation

- [Docker Compose Networking](https://docs.docker.com/compose/networking/)
- [Docker Network Drivers](https://docs.docker.com/network/drivers/)
- [Docker DNS](https://docs.docker.com/config/containers/container-networking/#dns-services)

### Network Troubleshooting

- [Nicolaka Netshoot](https://github.com/nicolaka/netshoot) - Network troubleshooting container
- [Docker Network Inspect](https://docs.docker.com/engine/reference/commandline/network_inspect/)

### Architecture Patterns

- [Microservices Network Patterns](https://microservices.io/patterns/communication-style/messaging.html)
- [Docker Security Best Practices](https://docs.docker.com/engine/security/)

### Tools

- [Docker Network Commands](https://docs.docker.com/engine/reference/commandline/network/)
- [Compose Network Reference](https://docs.docker.com/compose/compose-file/06-networks/)

Related Skills

docker-patterns

16
from diegosouzapw/awesome-omni-skill

Docker best practices, multi-stage builds, container security, Docker Compose orchestration, and deployment patterns. Use when containerizing applications, optimizing Docker images, setting up development environments, or deploying with Docker.

axiom-networking-diag

16
from diegosouzapw/awesome-omni-skill

Use when debugging connection timeouts, TLS handshake failures, data not arriving, connection drops, performance issues, or proxy/VPN interference - systematic Network.framework diagnostics with production crisis defense

compose-ui-control

16
from diegosouzapw/awesome-omni-skill

Control a running Compose Desktop application via HTTP. Use when you need to interact with UI elements, click buttons, enter text, wait for elements to appear, or capture screenshots in a Compose Desktop app that has compose-ui-test-server enabled.

android-ui-compose

16
from diegosouzapw/awesome-omni-skill

This skill is used to implement Android UI in Jetpack Compose based on an existing UX flow, focusing on clear hierarchy, list vs form separation and discoverable navigation.

android-jetpack-compose-expert

16
from diegosouzapw/awesome-omni-skill

Expert guidance for building modern Android UIs with Jetpack Compose, covering state management, navigation, performance, and Material Design 3.

xml-to-compose

16
from diegosouzapw/awesome-omni-skill

Convert Android XML layouts to Jetpack Compose. Use when asked to migrate XML layouts, convert views to composables, or help with Compose migration. Handles layouts, widgets, attributes, styles, and resource references.

workflow-composer

16
from diegosouzapw/awesome-omni-skill

Chain multiple skills together into automated workflows with conditional logic and parallel execution

docker-database

16
from diegosouzapw/awesome-omni-skill

Configure database containers with security, persistence, and health checks

composer-dependency-management

16
from diegosouzapw/awesome-omni-skill

Rules pertaining to Composer dependency management, promoting best practices for declaring and updating dependencies.

postgresql-docker

16
from diegosouzapw/awesome-omni-skill

PostgreSQL in containers - Docker, Kubernetes, production configs

bgo

10
from diegosouzapw/awesome-omni-skill

Automates the complete Blender build-go workflow, from building and packaging your extension/add-on to removing old versions, installing, enabling, and launching Blender for quick testing and iteration.

Coding & Development

file-suggestion

16
from diegosouzapw/awesome-omni-skill

Set up fast file suggestions for Claude Code using ripgrep, jq, and fzf. Use this skill when users want to improve file autocomplete performance or add custom file suggestion behavior.