Restrict Docker to a Private Network Between Hosts
This guide shows you how to configure Docker so that containers on different hosts communicate only over a private, isolated network—not the public internet. You’ll set up an overlay network with encryption, bind services to private IPs, and control firewall rules. This is useful for multi-host Docker deployments (e.g., Swarm or manual) where you want to keep inter-host traffic off public interfaces.
What You’ll Need
- Two or more Linux hosts with Docker Engine installed (version 19.03 or later recommended).
- Root or sudo access on each host.
- A private network between the hosts (e.g., a VPN, a dedicated VLAN, or a direct cable). All hosts must be able to reach each other on that network.
- Open ports on the private interface for Docker Swarm (if using Swarm) or for your custom overlay network.
- Basic familiarity with the command line and Docker CLI.
Step-by-Step
- Identify the private network interface on each host. Run
ip addrorifconfigto find the IP address that belongs to the private network (e.g., 10.0.0.1, 192.168.50.2). Note this IP—you’ll use it for all Docker configuration. - Configure Docker daemon to listen only on the private interface (if you need remote API access). Edit
/etc/docker/daemon.jsonand set thehostsarray to include only the private IP, for example:{"hosts": ["tcp://10.0.0.1:2375", "unix:///var/run/docker.sock"]}. Then restart Docker:sudo systemctl restart docker. This prevents Docker from binding to public interfaces. - Set up Docker Swarm (optional but recommended) for multi-host orchestration. On the first host, run
docker swarm init --advertise-addr 10.0.0.1(replace with your private IP). This forces Swarm to advertise the private IP. On other hosts, run the join command that Swarm outputs, but make sure to specify the private IP:docker swarm join --token <token> 10.0.0.1:2377. - Create an overlay network that is restricted to the private network. Run:
docker network create -d overlay --attachable --opt encrypted my-private-net. The--opt encryptedenables IPSEC encryption for traffic between hosts. If you’re not using Swarm, you can use a simple bridge network with manual routing, but overlay is the standard for multi-host. - Bind containers to the private network when you run them. For example:
docker run -d --network my-private-net --ip 10.0.0.50 nginx. This assigns a static IP from the overlay network. For services, usedocker service create --network my-private-net .... - Configure firewall rules to allow only necessary traffic on the private interface. On each host, use iptables or ufw to allow traffic on the private interface (e.g.,
sudo ufw allow in on eth1 to any port 2377 proto tcpfor Swarm, andsudo ufw allow in on eth1 to any port 7946 proto tcpandudpfor gossip). Deny these ports on public interfaces. - Test connectivity between containers on different hosts. From a container on host A, ping a container on host B using its private IP. For example,
docker exec -it containerA ping 10.0.0.50. If ping fails, check that the overlay network is functioning and that the hosts can reach each other on the private network. - Verify that no traffic goes over public interfaces. Use
tcpdumpon the public interface to see if any Docker-related traffic appears. It should be silent for inter-host container traffic.
Common Mistakes
- Using the default bridge network for inter-host communication—it doesn’t work across hosts.
- Forgetting to specify
--advertise-addrwhen initializing Swarm, causing it to pick the public IP. - Not opening the required ports on the private interface, leading to timeouts.
- Using the same IP range for the overlay network as the host’s private network, causing conflicts.
- Assuming that encryption is enabled by default—you must add
--opt encrypted.
Tips
- Use a dedicated subnet for your overlay network, e.g., 10.10.0.0/16, to avoid overlap.
- For non-Swarm setups, consider using WireGuard or VXLAN to create a private tunnel between hosts, then use a simple bridge network.
- Always use
--attachableif you want standalone containers to join the overlay network. - Set the
DOCKER_HOSTenvironment variable to the private IP if you’re using remote Docker from a client. - Document your network topology and IP assignments to avoid confusion.
Troubleshooting
- Containers can’t ping each other: Check that the overlay network is created on both hosts (
docker network ls). Ensure that the hosts can ping each other on the private IP. Verify that the firewall allows ICMP on the private interface. - Swarm join fails: Make sure the join command uses the private IP and that port 2377 is open on the private interface. Also check that the token is correct.
- Docker daemon doesn’t start after changing hosts: Check the daemon.json syntax with
docker daemon --validate. Ensure the directory/etc/dockerexists and the file is readable. - Traffic still goes over public interface: Use
tcpdump -i eth0 port 4789(VXLAN port) to see if overlay traffic is leaking. If so, check the routing table—maybe the private network isn’t the default route for the overlay subnet. - Encryption not working: Confirm that both hosts have the same encryption key (Docker handles this automatically in Swarm). If you’re not using Swarm, you’ll need to set up a secure tunnel manually.
Frequently Asked Questions
Do I need Docker Swarm to use an overlay network?
Yes, overlay networks are a Swarm feature. However, you can use Swarm in a single-node mode or use a third-party solution like Weave or Flannel if you prefer not to use Swarm.
Can I restrict Docker to a private network without using Swarm?
Yes, you can use a bridge network on each host and manually configure routing or a VPN tunnel between them. But this is more complex and less scalable than using Swarm’s overlay network.
How do I make the overlay network encrypted?
Add the --opt encrypted flag when creating the network. This enables IPSEC encryption for all traffic on that network.
What ports do I need to open for Swarm to work?
For Swarm, you need to open TCP port 2377 for cluster management, and TCP/UDP port 7946 for node communication, and UDP port 4789 for overlay network traffic. Open these only on the private interface.
Can I use the same IP range for the overlay network as my host’s private network?
It’s not recommended because it can cause routing conflicts. Use a different subnet, like 10.10.0.0/16, for the overlay network.
How do I assign a static IP to a container on the overlay network?
When running a container, use the --ip flag with the desired IP address from the overlay network’s subnet. For example, docker run --network my-net --ip 10.10.0.5 nginx.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.