Quick Summary: The error
Error response from daemon: Pool overlaps with other one on this address spaceoccurs when Docker attempts to create a new bridge network (for example, duringdocker compose upordocker network create) and the auto-assigned IPv4 CIDR subnet collides with an existing Docker network, a host interface, or an active corporate VPN tunnel (such as OpenVPN, WireGuard, or Cisco AnyConnect).
Understanding the Root Causes
By default, the Docker daemon allocates bridge subnets sequentially from the private 172.17.0.0/16 through 172.31.0.0/16 and 192.168.0.0/20 IPv4 pools. When Docker initializes a new network, it checks the host kernel routing table for conflicting routes. The operation aborts if:
- Corporate VPN Route Overlap: Connecting to a VPN injects
172.16.0.0/12or192.168.x.xroutes into the host routing table, blocking Docker’s default address pool allocation. - Stale or Unused Docker Networks: Accumulating dozens of orphaned bridge networks from previous Compose projects exhausts available
/16or/20subnets, or leaves behind conflicting static subnets. - Duplicate Static Subnet Definitions: Two different
docker-compose.ymlfiles explicitly declaring the same customsubnetCIDR block.
Step 1: Quick Fix – Prune Unused Docker Networks
If subnet exhaustion or leftover project networks are causing the collision, inspect and clean up unused networks first:
# 1. List all existing Docker networks
docker network ls
# 2. Inspect subnets currently assigned to Docker networks
docker network inspect $(docker network ls -q) --format '{{.Name}}: {{range .IPAM.Config}}{{.Subnet}}{{end}}'
# 3. Remove all unused networks not referenced by any container
docker network prune -f
# 4. Retry your Docker Compose stack
docker compose up -d
Step 2: Configure Custom Default Address Pools in daemon.json
If your corporate VPN or local LAN occupies the 172.17.x.x–172.31.x.x space, configure the Docker daemon to allocate smaller /24 subnets from an unused private range (such as 10.200.0.0/16):
# 1. Inspect host routing table to find an unused private IP range
ip route show
# 2. Edit or create /etc/docker/daemon.json (on Linux)
# On Docker Desktop (macOS/Windows), edit Settings -> Docker Engine
sudo nano /etc/docker/daemon.json
# Add the default-address-pools configuration:
{
"default-address-pools": [
{
"base": "10.200.0.0/16",
"size": 24
}
]
}
# 3. Restart the Docker daemon to apply the new pool
sudo systemctl restart docker
Using "size": 24 provides up to 256 distinct /24 networks (each supporting 254 containers) instead of exhausting large /16 blocks.
Step 3: Assign a Non-Conflicting Subnet in docker-compose.yml
When you only need to resolve a collision for a single project without modifying global daemon settings, define an explicit IPAM subnet in docker-compose.yml:
services:
app:
image: nginx:alpine
networks:
- custom_net
networks:
custom_net:
driver: bridge
ipam:
config:
- subnet: 10.250.10.0/24
gateway: 10.250.10.1
Verification & Testing Steps
Verify that Docker allocates networks from your new address pool and that no routing conflicts remain:
# 1. Create a test bridge network and inspect its assigned CIDR
docker network create test-pool-net
docker network inspect test-pool-net --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
# Expected output (if using 10.200.0.0/16 with /24 size):
# 10.200.0.0/24
# 2. Clean up the test network
docker network rm test-pool-net
# 3. Verify your Compose stack starts cleanly
docker compose up -d && docker compose ps
Troubleshooting Summary Comparison
| Scenario | Primary Root Cause | Recommended Solution |
|---|---|---|
| Too many old Compose stacks | Orphaned networks exhausted default pools | Run docker network prune -f |
| Fails only when VPN is active | VPN routes overlap 172.17.0.0/12 |
Set default-address-pools in daemon.json |
| Single project subnet collision | Hardcoded subnet matches another stack |
Define a unique ipam.config.subnet in Compose |
| Large multi-stack host | Default /16 pools run out after ~30 networks |
Configure smaller "size": 24 subnets globally |
Leave a Reply