Docker Compose Networking: Avoiding Subnet Conflicts with Custom Address Pools

Docker Compose Networking: Avoiding Subnet Conflicts with Custom Address Pools
Photo by Faizur Rehman / Unsplash

When working with Docker Compose, each time you run a new compose file, it automatically creates its own network. While this default behavior promotes isolation between different applications, it can lead to unexpected networking issues if not properly managed. Let's dive into why this happens and how to prevent potential problems.

The Default Behavior

By default, when Docker Compose creates a new network, it allocates a /20 subnet. This means each network gets a relatively large block of IP addresses (4,096 addresses to be exact). Docker automatically selects the subnet from its default address pools, which can include ranges like 192.168.0.0/20, 192.168.16.0/20, and so on.

Here's where the problem comes in: 192.168.1.0/24 (for example) as is one of the most commonly used subnets for home and small office networks. If Docker happens to create a network that overlaps with this range, you might experience connectivity issues reaching devices on that subnet.

For example, if Docker creates a network with 192.168.0.0/20, it encompasses:

  • 192.168.0.0 through 192.168.15.255
  • This includes 192.168.1.0/24, which might be your local network

The Solution: Custom Address Pools

To prevent these conflicts, we can configure Docker to use specific address ranges and smaller subnet sizes. Here's how to do it system-wide:

  1. Create or edit /etc/docker/daemon.json:
{
  "default-address-pools": [
    {
      "base": "172.30.0.0/16",
      "size": 24
    },
    {
      "base": "172.31.0.0/16",
      "size": 24
    }
  ]
}

This configuration tells Docker to:

  • Use the 172.30.0.0/16 and 172.31.0.0/16 ranges for new networks
  • Allocate /24 networks (256 addresses each) instead of /20
  • Stay away from the commonly used 192.168.0.0/16 range entirely

After saving this configuration, restart the Docker daemon:

sudo systemctl restart docker

Benefits of This Approach

  1. Smaller Networks: Using /24 instead of /20 means each network gets 256 addresses instead of 4,096. This is usually more than enough for most applications.
  2. Predictable Ranges: By using 172.30.0.0/16 and 172.31.0.0/16, we avoid conflicts with common local network ranges.
  3. More Networks: With this configuration, Docker can create up to 512 different networks (256 from each /16 pool), each with their own /24 subnet.

Alternative: Per-Compose Configuration

If you prefer to configure this on a per-project basis, you can specify the subnet in your docker-compose.yml file:

networks:
  default:
    ipam:
      config:
        - subnet: 172.30.1.0/24

Conclusion

By taking control of Docker's network address allocation, we can prevent the headaches caused by subnet conflicts. The system-wide configuration approach ensures that all automatically created networks follow our rules, making it easier to maintain a stable networking environment across all our Docker projects.

Remember: prevention is better than cure. Setting up proper network ranges before you encounter conflicts will save you troubleshooting time in the future.