A deep dive into Docker networking strategies for scalable browser automation. We analyze why the industry moved from rigid links to flexible orchestration.
Historical Context & Limitations
In the early days of Docker (pre-2016), the only way for two containers to talk was the --link flag. This method worked by injecting the IP address of the target container directly into the /etc/hosts file of the source container.
Here is what the legacy setup looked like. Note the rigid dependency direction:
# 1. Start the Hub first (Critical dependency)
docker run --name hub -d -p 4444:4444 selenium/hub
# 2. Hard-link the Chrome node to the Hub
docker run --name chrome -d --link hub:selenium selenium/node-chrome-debug
Orchestration & Service Discovery
Modern Docker setups utilize User-Defined Bridge Networks. Instead of injecting IPs, Docker runs an internal DNS server at 127.0.0.11.
When the Chrome node tries to reach http://hub:4444, Docker intercepts the request and resolves "hub" to the current IP address of the hub container. If the Hub restarts and gets a new IP, the DNS updates automatically, and the grid heals itself.
Below is a robust docker-compose.yml. Notice the use of shm_size—a critical setting for browser stability.
version: "3"
services:
hub:
image: selenium/hub
container_name: hub
ports:
- "4444:4444"
healthcheck:
test: ["CMD", "/opt/bin/check-grid.sh", "--host", "0.0.0.0", "--port", "4444"]
interval: 15s
timeout: 30s
chrome:
image: selenium/node-chrome
depends_on:
- hub
environment:
- SE_EVENT_BUS_HOST=hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
# CRITICAL: Fixes "Chrome crashed" errors on complex pages
shm_size: "2gb"
ports:
- "5900"
| Feature | Legacy (--link) | Docker Compose (Network) |
|---|---|---|
| Discovery Mechanism | Environment Variables & /etc/hosts injection |
Internal DNS Resolution (127.0.0.11) |
| Resilience | Low Breaks on container restart | High Self-healing connections |
| Scaling | Manual (Must assign unique ports manually) | Automatic (docker-compose up --scale chrome=5) |
One detail often missed in basic tutorials is the /dev/shm partition. By default, Docker containers are allocated 64MB of shared memory. Modern browsers (Chrome/Firefox) use this memory space extensively for rendering tabs.
The Fix: If your Selenium tests crash randomly with "Session Deleted" or "Chrome failed to start," it is likely a memory issue. Always set shm_size: '2gb' or map the volume -v /dev/shm:/dev/shm in your Compose file to resolve this.