Skip to content

# Docker Networks

## Current Landscape (May 16, 2026)

Each Docker Compose stack creates its own `{stack}_default` bridge network when it has no explicit `networks:` declaration. This has exhausted Docker's built-in 172.x.x.x/16 address pool, triggering CIDR overlap errors.

### Networks & Subnets

Network | Subnet | Containers
--- | --- | ---
`bridge` (built-in) | 10.0.0.0/24 | 0
`ai-internal` | 172.31.0.0/16 | 8
`arcane_default` | 172.22.0.0/16 | 1
`arr-stack_default` | 172.21.0.0/16 | 4
`dozzle_default` | 192.168.16.0/20 | 1
`homepage_default` | 172.19.0.0/16 | 1
`immich_default` | 172.18.0.0/16 | 5
`karakeep_default` | 172.30.0.0/16 | 3
`memos_default` | 192.168.32.0/20 | 1
`n8n_default` | 172.25.0.0/16 | 1
`ntfy_default` | 172.27.0.0/16 | 1
`nuc-ai-core_default` | 172.29.0.0/16 | 1
`paperless-ngx_default` | 172.28.0.0/16 | 5
`pocketid_default` | 172.20.0.0/16 | 1
`qdrant_default` | 172.24.0.0/16 | 1
`traccar_default` | 172.26.0.0/16 | 1
`vaultwarden_default` | 192.168.64.0/20 | 1
`vpn_default` | 192.168.80.0/20 | 1

Total: 18 user-defined bridge networks (Daytona decommissioned 2026-05-20).

### Problem

Docker's default address pool for user-defined bridge networks is 172.17.0.0/16 – 172.31.0.0/16 (15 subnets max). With 15 172.x.x.x/16 networks already allocated, there is no room for new ones.

The Daytona runner (`daytona-minimal-runner-1`) programmatically creates a `runner-bridge` network on startup. It fails with:

    Error response from daemon: invalid pool request: Pool overlaps with other one
    on this address space

## Consolidation Plan

### shared_backend Network

A single shared bridge network (`shared_backend`) has been created to replace per-stack defaults for lightweight services that don't need isolation.

### Stacks Already Migrated

- arcane
- dozzle
- ntfy
- qdrant
- traccar
- vaultwarden
- memos
- n8n
- pocketid

These stacks now declare:

    networks:
      default:
        external: true
        name: shared_backend

### How to Free Subnets

After migrating a stack to `shared_backend`, recreate it and prune the old network:

    cd /opt/stacks/{stack} && docker compose up -d
    docker network rm {stack}_default   # after containers disconnect

### Stacks Keeping Own Networks

These stacks have complex internal networking and should keep their own:

- immich — 5 services with inter-dependencies
- paperless-ngx — 5 services (webserver, broker, db, gotenberg, tika)
- arr-stack — 5 services (rdtclient, prowlarr, audiobookshelf, shelfarr, flaresolverr)
- karakeep — 3 services with chrome dependency
- homepage — single service, can stay or migrate
- streamio — already removed, stremio uses VPN container directly
- vpn — single service, can stay or migrate
- ai/*_ai — AI stacks, untouched

### Long-term Fix

Add `default-address-pools` to `/etc/docker/daemon.json`:

    {
      "default-address-pools": [
        {"base": "10.0.0.0/8", "size": 24}
      ]
    }

This gives 65536 /24 subnets, eliminating exhaustion. Requires Docker daemon restart (`systemctl restart docker`), which briefly disrupts all containers.

## Commands

    # List all networks
    docker network ls

    # Inspect a network
    docker network inspect {name}

    # Remove unused networks
    docker network prune

    # Remove a specific network (must have 0 containers)
    docker network rm {name}