Introduction
By default, Docker containers attached to the bridge network can freely communicate with one another. While this behavior is convenient for development and testing, it poses a potential security risk in production environments. Containers on the same network should not always have unrestricted access to each other, especially when dealing with sensitive applications or microservices. In this detailed guide, you will learn how to restrict container-to-container network traffic on Docker's default bridge network, understand the challenges, and explore secure alternatives to isolate communication.
1. Understanding Docker's Default Bridge Network
Before diving into restricting inter-container communication, I recommend checking out my previous blog posts, "Understanding Docker’s Default Networking Modes", and "Creating Custom Docker Networks" where I cover Docker's networking fundamentals, including bridge networks and custom network setups.
When Docker is installed, it creates a default network called bridge. Containers attached to this network can:
- Communicate with each other via their internal IP addresses.
- Access the host machine and external networks.
To list Docker networks and identify the bridge network, use:
docker network ls
Output:
NETWORK ID NAME DRIVER SCOPE
abcd12345678 bridge bridge local
efgh23456789 host host local
ijkl34567890 none null local
By default, all containers without a specific network configuration attach to the bridge network.
2. Demonstrating the Problem: Free Communication
To illustrate, let’s create two containers attached to the default bridge:
Step 1: Run Two Containers
Start two containers and attach them to the default bridge network:
docker run -dit --name container1 alpine sh
docker run -dit --name container2 alpine sh
Step 2: Verify Connectivity
Attach to container1 and ping container2's IP address:
Access container1 and ping container2:
docker exec -it container1 sh
ping 172.17.0.3
You’ll see successful pings, confirming that the containers can communicate freely.
Find the IP address of container2:
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container2
Example output: 172.17.0.3
3. Why Restrict Container-to-Container Communication?
Unrestricted communication between containers can lead to the following risks:
- Unauthorized Access: Malicious containers can access sensitive services running on other containers.
- Network Noise: Containers may send unnecessary traffic to each other.
- Isolation Breach: Containers running different applications may unintentionally interact, compromising security.
To address this, you need to restrict container-to-container traffic on the default bridge network.
4. Configuring icc to Restrict Inter-Container Traffic
Docker provides the icc (Inter-Container Communication) option, which controls whether containers on the bridge network can communicate. By default, icc is set to true, allowing free communication.
Step 1: Edit the Docker Daemon Configuration
Open or create the Docker daemon configuration file /etc/docker/daemon.json:
sudo nano /etc/docker/daemon.json
Add or modify the following option to disable inter-container communication:
{
"icc": false
}
Save the file and restart the Docker daemon to apply the changes:
sudo systemctl restart docker
Step 2: Verify icc Configuration
- Test Restricted Traffic: You will see that the ping now fails, demonstrating that inter-container communication has been disabled.
- Try pinging
container2fromcontainer1.
docker exec -it container1 sh
ping 172.17.0.3
Repeat the steps to create two containers:
docker run -dit --name container1 alpine sh
docker run -dit --name container2 alpine sh
Confirm the Docker daemon configuration with:
docker info | grep "icc"
Output:
Inter-Container Communication: false
5. Limitations of the icc Setting
While disabling icc restricts communication on the default bridge network, it does not provide fine-grained control over network traffic. Key limitations include:
- Global Setting: The
iccoption affects all containers on the bridge network. - No Selective Rules: You cannot allow communication for specific containers or services.
- Custom Networks Are Unaffected: This setting only impacts the default bridge network, not user-defined networks.
For more control, you can use user-defined bridge networks and Docker’s built-in firewall capabilities.
6. Using User-Defined Bridge Networks for Isolation
Docker allows you to create custom bridge networks that can isolate container communication. By default, containers on a user-defined network cannot communicate unless explicitly configured.
Step 1: Create a User-Defined Bridge Network
Run the following command to create a custom bridge network:
docker network create my_secure_network
Step 2: Run Containers in the Custom Network
Attach containers to the new network:
docker run -dit --name container1 --network my_secure_network alpine sh
docker run -dit --name container2 --network my_secure_network alpine sh
Step 3: Verify Isolation
- Test Communication: Ping
container2fromcontainer1. By default, this will succeed. - Restrict Communication: Use Docker network policies or an external firewall like iptables to block traffic selectively.
7. Restrict Traffic Using iptables (Advanced)
For granular control, you can configure firewall rules with iptables to restrict communication between containers.
Step 1: List Docker-Related Rules
Docker automatically creates iptables rules when containers start. To view the rules:
sudo iptables -L -v -n
Step 2: Add Rules to Block Container Traffic
To block traffic between containers on the bridge network, add the following rule:
sudo iptables -I FORWARD -i docker0 -o docker0 -j DROP
docker0is the default bridge interface.- This rule blocks traffic between containers on the bridge network.
Step 3: Test the Rule
- Create two containers and verify they cannot ping each other.
To revert the rule, delete it:
sudo iptables -D FORWARD -i docker0 -o docker0 -j DROP
8. Best Practices for Restricting Container Communication
- Use Custom Bridge Networks: Replace the default bridge network with user-defined networks for better isolation.
- Disable
icc: Seticc: falseto globally disable inter-container communication on the default bridge. - Implement Firewall Rules: Use
iptablesfor advanced traffic restrictions. - Network Segmentation: Place containers that require communication in the same network and isolate others.
- Audit and Monitor: Regularly audit network traffic to detect unauthorized communication.Conclusion
Restricting container-to-container communication on the default bridge network is a critical step toward improving Docker security. While disabling the icc setting offers a quick solution, user-defined networks and firewall rules provide more control and flexibility. By following the steps outlined in this guide, you can secure your Docker environment, reduce unnecessary network exposure, and mitigate potential risks.