跨主机连接两个Docker容器的可行方案咨询(已试Swarm/Weave未果)
Hey there! Sorry to hear you've hit snags with Docker Swarm and Weave when trying to connect your web container on Host A to the DB container on Host B. Let's break down some reliable, actionable solutions that should get things working:
If you need a fast, no-frills solution, this is the way to go—great for testing or small setups:
- On Host B, start your DB container with a port mapped to Host B's internal or public IP (stick to internal if possible for security). For example, with PostgreSQL:
docker run -d -p <HostB_INTERNAL_IP>:5432:5432 --name my-db -e POSTGRES_PASSWORD=yoursecurepassword postgres - On Host A, configure your web app to connect to
<HostB_INTERNAL_IP>:5432instead of a container name. - Critical Checks: Make sure Host A and Host B can reach each other over the network (test with
ping <HostB_INTERNAL_IP>) and that your firewall/security group allows incoming traffic on the DB port (5432 in this example). - Pro Tip: Avoid exposing the DB port to the public internet if you can—use your internal network or a VPN for remote setups.
Chances are your earlier Swarm attempt failed due to missing port openings or incorrect network configuration. Here's the step-by-step correct setup:
- Initialize Swarm on Host A:
Copy thedocker swarm init --advertise-addr <HostA_INTERNAL_IP>docker swarm joincommand that's output—you'll need it for Host B. - Join Host B to the Swarm:
Run the copied join command on Host B (it'll look like this, with your unique token):docker swarm join --token SWMTKN-1-xxxxxx <HostA_INTERNAL_IP>:2377 - Create an Attachable Overlay Network:
This lets standalone containers (not just Swarm services) connect to the network:docker network create --driver overlay --attachable cross-host-net - Launch Containers on the Network:
- On Host A:
docker run -d --name my-web --network cross-host-net your-web-image - On Host B:
docker run -d --name my-db --network cross-host-net your-db-image
- On Host A:
- Test the Connection:
Inside your web container, you can now connect to the DB using the container namemy-db(Swarm's overlay network handles service discovery automatically).
- Why You Might Have Failed Before: Ensure these ports are open on both hosts:
- 2377 (Swarm management)
- 7946 (node-to-node communication)
- 4789 (overlay network data traffic)
Perfect if you're working across cloud providers or remote machines without a dedicated internal network:
- Install Tailscale (or WireGuard) on both Host A and Host B. Once logged in, both hosts will be part of a secure virtual network with unique internal IPs.
- You can either:
- Use the port mapping method above, but replace Host B's IP with its Tailscale virtual IP.
- Or, for a cleaner setup, create a bridge network on each host and use Tailscale to forward the DB container's port to Host A (though port mapping is simpler for most cases).
- The best part? No complex network config—Tailscale handles encryption and routing out of the box.
For larger, distributed systems where you need service discovery and encrypted connections:
- Deploy a Consul agent on both Host A and Host B to form a small Consul cluster.
- Configure Docker Connect to register your web and DB containers as services in Consul.
- Your web container can then access the DB using its Consul service name, and Connect will automatically establish a secure, encrypted connection between the two containers across hosts.
- This is overkill for simple setups, but ideal if you're scaling to more containers or hosts.
Quick Troubleshooting Tips
Before diving into any solution, confirm:
- Host A can ping Host B and vice versa.
- You can telnet to the DB port from Host A:
telnet <HostB_IP> <DB_PORT>—if this fails, your firewall is blocking traffic. - Check container logs with
docker logs my-webordocker logs my-dbto see specific connection errors (e.g., "connection refused" vs "timeout").
内容的提问来源于stack exchange,提问作者Rakesh Sivagouni

