Docker Swarm Across Three Continents: High Availability Designed for 100% Uptime

Published on 20 min read

One data center is a single point of failure. This article builds a Docker Swarm across three continents that can survive the loss of an entire location: manager quorum, WireGuard, one entry point per region, Geo-DNS failover, database replication and operations.

A server in a data center is a single point of failure, no matter how good the hardware and the network are. If that location goes down, whether because of a power or network fault or simply a mistake during maintenance, the application is gone. Docker Swarm across multiple data centers solves exactly this problem: the containers run at three independent locations, ideally on three continents, and if one of them fails completely, the other two take over without users noticing a thing.

This article shows you step by step how to build a Docker Swarm cluster designed for 100% uptime: one server each in North America, Europe and Asia, an encrypted WireGuard network between the nodes, a manager quorum that survives the loss of an entire continent, one entry point per region and a DNS failover that automatically routes users to the nearest healthy location. We also explain honestly what can still fail even with this architecture and how to cover those risks as well.

Can Docker Swarm achieve 100% uptime?

A Docker Swarm across three continents is designed for 100% uptime: no single server, no single data center and no single continent can bring the application to a standstill on its own. Even so, nobody can guarantee absolute availability, not even the big cloud providers, whose highest commitments range from 99.99 to 99.999%. The reason is not the data centers but the things that all locations have in common. This article covers exactly those as well, so that you get as close to 100% as is technically possible.

What availability means in numbers

AvailabilityDowntime per yearDowntime per month
99%87.6 hours7.3 hours
99.9%8.76 hours43.8 minutes
99.99%52.6 minutes4.4 minutes
99.999%5.3 minutes26 seconds

The figures are based on 8,760 hours per year and 730 hours per month. Each additional nine cuts the permitted downtime to a tenth, and that is exactly where the work begins that a single server can no longer handle.

Why three continents make such a difference

Mathematically, three independent locations with 99.9% availability each only fail together if all three are disrupted at the same time: 0.1% times 0.1% times 0.1% equals 0.0000001%. The farther apart the locations are, the more independent they really are: separate power grids, separate network connections, separate weather, separate maintenance windows. That is why spreading the cluster across North America, Europe and Asia is the strongest form of resilience that can be built with servers.

What can still fail even with three continents

The remaining risks are the dependencies that all locations share, and there is a countermeasure for each of them:

  • A faulty update is distributed by the cluster to all locations just as reliably as a good one. Countermeasure: health checks and automatic rollback, plus updates region by region.
  • DNS is the one place that every user passes through. Countermeasure: a DNS provider with a globally distributed network and failover, and a short TTL.
  • The database has to hold the same data at every location. Countermeasure: replication with automatic failover, see the section on data.
  • Expired certificates and domains hit all locations at the same time. Countermeasure: automatic renewal and monitoring of the expiration dates.
  • The switchover itself takes as long as the health checks and DNS need to react, usually one to two minutes during which individual requests can fail. Countermeasure: short check intervals, a short TTL and clients that retry failed requests.

The architecture at a glance

A Docker Swarm across multiple continents consists of six building blocks. Each of them eliminates a specific point of failure:

Building blockRoleFailure it protects against
Three manager nodes on three continentsMaintain the cluster state through Raft consensusLoss of an entire location or continent
Worker capacity in every regionRuns the containers close to the usersFailure of individual servers
WireGuard network between all nodesEncrypts all cluster traffic across the internetEavesdropping and tampering between the data centers
Entry point (reverse proxy) per regionAccepts user requests and answers them locallyFailure of a region's entry point
Geo-DNS with health checksSends users to the nearest healthy locationUnreachable locations
Replicated data storage and backupsKeeps databases and files in several placesData loss when a location fails

How many managers, and where?

The manager nodes of a swarm maintain the cluster state using the Raft consensus algorithm. Every change needs the approval of a majority of the managers, known as the quorum. If the majority is lost, the existing containers keep running, but the cluster can no longer reschedule, compensate for failures or roll out updates.

ManagersMajorityTolerated failures
321
532
743

Docker recommends an odd number of managers distributed across at least three zones, in a 1-1-1 split with three managers and 2-2-1 with five. This leads to the most important rule in this article: Two locations are not enough. With two locations, one of them inevitably holds more managers, and if exactly that one fails, the majority is gone. Only with three locations does the quorum survive the loss of any one data center, which with three continents means the loss of an entire continent.

Three continents or one: the trade-off

Every change to the cluster, every deployment and every rescheduling of a container waits for confirmation from the manager majority. Between Europe, North America and Asia, each of these confirmations involves a network latency of about 80 to 250 milliseconds. For users this makes no difference, because their requests are answered locally; deployments and rescheduling, however, take noticeably longer than in a cluster with short network paths.

OptionStrengthsTrade-offs
Three continents (USA, Europe, Asia)Maximum independence, users worldwide close to a server, an entire continent can failSlower cluster management, database replication over long distances, requests have to stay local
Three locations on one continent (for example Frankfurt, Strasbourg, Warsaw)Fast cluster management, simple synchronous replicationA large-scale event on the continent hits all locations, more distant users have longer paths

For applications with users on several continents and the goal of maximum availability, the three-continent option is the right choice, and it is what we build in this guide. One important rule runs through every step: each request is answered in its own region and never travels back and forth between continents.

Which KernelHost locations are suitable

KernelHost runs servers in the maincubes data center in Frankfurt am Main and offers virtual servers at further locations in Europe, North America and Asia-Pacific, including three locations in the USA as well as Canada, London, Strasbourg, Warsaw, Helsinki, Singapore, Japan, Sydney and Mumbai. The complete list with a map is on the server locations page. For the example in this article, we use Frankfurt am Main for Europe, the US East Coast for North America and Singapore for Asia.

Guide: building a Docker Swarm across three continents

The example uses three servers: swarm-eu in Frankfurt am Main, swarm-us on the US East Coast and swarm-asia in Singapore. The public addresses come from the documentation range 203.0.113.0/24, and the WireGuard network uses 10.10.0.0/24. Replace both with your own values. All three nodes are managers and workers at the same time; for more capacity, add worker-only nodes in each region later.

Step 1: Provision servers on three continents

Order three servers running Debian 12 or 13 in three regions and apply the basic hardening: SSH with keys only, automatic security updates, your own user accounts. The checklist for new root servers covers this. Give the servers descriptive hostnames so that you can tell right away in docker node ls which node is where.

hostnamectl set-hostname swarm-eu

Step 2: Install Docker on all nodes

Install Docker Engine from the official Docker repository on all three servers, as described in the article Installing Docker on Debian and Ubuntu. Then check the version on each node; all three should run the same major version:

docker version --format '{{.Server.Version}}'

Step 3: Build a WireGuard network between the continents

The nodes talk to each other over the public internet. So that all cluster traffic is encrypted and the Swarm ports are never publicly reachable, a WireGuard network connects the three servers. On each node, first generate a key pair:

apt-get install -y wireguard
umask 077
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key

Each node then gets a file at /etc/wireguard/wg0.conf. This is what it looks like on swarm-eu; the other two nodes are set up as mirror images:

[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = SWARM_EU_PRIVATE_KEY
MTU = 1420

[Peer]
PublicKey = SWARM_US_PUBLIC_KEY
Endpoint = 203.0.113.12:51820
AllowedIPs = 10.10.0.2/32
PersistentKeepalive = 25

[Peer]
PublicKey = SWARM_ASIA_PUBLIC_KEY
Endpoint = 203.0.113.13:51820
AllowedIPs = 10.10.0.3/32
PersistentKeepalive = 25
systemctl enable --now wg-quick@wg0
ping -c 3 10.10.0.2

Once all nodes answer on their 10.10.0.x addresses, the network is up. PersistentKeepalive keeps the connection open even behind stateful firewalls. The latencies that ping now reports between the continents are exactly the delays that every change to the cluster will cost.

Step 4: Firewall: only the Swarm nodes get in

Between the nodes, Docker Swarm needs port 2377/TCP for cluster management, 7946/TCP and UDP for communication among the nodes and 4789/UDP for the overlay network. Allow these ports on the WireGuard interface only; the only thing that stays open to the public is WireGuard itself, and only for the other nodes. With ufw, this looks as follows on swarm-eu:

ufw allow from 203.0.113.12 to any port 51820 proto udp
ufw allow from 203.0.113.13 to any port 51820 proto udp
ufw allow in on wg0 to any port 2377 proto tcp
ufw allow in on wg0 to any port 7946
ufw allow in on wg0 to any port 4789 proto udp

Important: ports that Docker publishes for containers bypass ufw, because Docker sets its own iptables rules. So publish only the entry point's ports (80 and 443) and never database or management ports.

Step 5: Initialize the swarm and add managers

On swarm-eu, initialize the swarm and make sure that both management and data traffic run over WireGuard:

docker swarm init --advertise-addr 10.10.0.1 --data-path-addr 10.10.0.1
docker swarm join-token manager

The second command prints the join command for additional managers. Run it on swarm-us and swarm-asia, each with its own WireGuard address, shown here for swarm-us:

docker swarm join --token SWMTKN-1-... --advertise-addr 10.10.0.2 --data-path-addr 10.10.0.2 10.10.0.1:2377
docker node ls

docker node ls then shows three nodes, one of them with the status Leader and the other two with Reachable. The join token is a secret: anyone who knows it can sneak a manager of their own into your cluster. Once the setup is complete, rotate it with docker swarm join-token --rotate manager.

Step 6: Enable autolock

The managers store the cluster state, including the keys used to encrypt the Raft logs, under /var/lib/docker/swarm/. With autolock, these keys are encrypted themselves, and a restarted manager only rejoins the cluster after an unlock key has been entered:

docker swarm update --autolock=true
docker swarm unlock

The first command prints the unlock key, which you store in a password manager. You need the second one after every restart of a manager. Without the key, the swarm cannot be restored even from a backup, so keep it separate from the servers.

Step 7: Label the nodes by region

Labels tell the scheduler where a node is located. The placement constraints in the following steps build on them:

docker node update --label-add region=eu swarm-eu
docker node update --label-add region=us swarm-us
docker node update --label-add region=asia swarm-asia

Step 8: Create an overlay network with the right MTU

Containers at different locations talk to each other over an overlay network. Because it runs through the WireGuard tunnel, its MTU has to be smaller: WireGuard works with 1420 bytes, the overlay network (VXLAN) needs 50 of those bytes for its own headers, which leaves 1370 bytes:

docker network create --driver overlay --attachable --opt com.docker.network.driver.mtu=1370 appnet

An MTU that is too large causes insidious symptoms: small requests work, large responses hang. If you do without WireGuard, you can encrypt the overlay network with --opt encrypted instead; in that case, IP protocol 50 (ESP) must also be allowed between the nodes, and Docker explicitly warns of a noticeable performance penalty. We recommend WireGuard because it covers all traffic, including management.

Step 9: Run the application in every region

A regular Swarm service distributes requests through its service address across all replicas in the cluster, including those on the other continents. With three continents, every second or third request would then travel halfway around the world. That is why each region gets its own service, which a placement constraint keeps in its region. The update settings make sure that new versions are rolled out one container at a time and automatically rolled back if errors occur:

for r in eu us asia; do
  docker service create --name web-$r --replicas 2 --network appnet \
    --constraint node.labels.region==$r \
    --update-parallelism 1 --update-delay 30s \
    --update-failure-action rollback \
    registry.example.com/web:1.0
done

For Swarm to recognize whether a container is actually working and not just running, the image needs a health check, for example this line in your application's Dockerfile:

HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD wget -qO- http://127.0.0.1:8080/health || exit 1

A container whose health check fails three times in a row gets replaced, and during an update a failing health check stops the rollout.

Step 10: One entry point per region

A reverse proxy such as Caddy, Traefik or nginx acts as the entry point. It also runs as a separate service in each region and forwards requests only to the application in its own region. In host mode, it publishes ports 80 and 443 directly on the server in its region. A single shared configuration is enough, because Caddy reads the target from an environment variable:

example.com {
    reverse_proxy {$UPSTREAM}:80
}
docker config create caddyfile ./Caddyfile
for r in eu us asia; do
  docker service create --name edge-$r --network appnet \
    --constraint node.labels.region==$r \
    --env UPSTREAM=web-$r \
    --config source=caddyfile,target=/etc/caddy/Caddyfile \
    --publish mode=host,target=80,published=80 \
    --publish mode=host,target=443,published=443 \
    caddy:2
done

Every region needs a TLS certificate for the same domain. So obtain the certificates through the DNS challenge, which works regardless of which region the DNS record currently points to; for this, Caddy needs the module for your DNS provider. The proxy basics are covered in the article Setting up nginx as a reverse proxy.

Step 11: Set up Geo-DNS with failover

The last building block routes users to the right region. A DNS service with geo-routing and health checks sends users from Europe to Frankfurt am Main, users from the Americas to the US East Coast and users from Asia to Singapore. If a region fails, the health check detects this within 30 to 60 seconds and sends that region's users to the nearest healthy region. Set the time to live (TTL) of the records to 60 seconds so that resolvers pick up a change quickly. Multiple A records without a health check are only a stopgap: browsers often try the next address, but not every client does, and a failed region stays in the response.

Do the math honestly: the time between the failure and the switchover is the check interval plus the TTL, in this example one to two minutes, during which some of the users in the affected region still reach the failed location. Applications and apps that retry failed requests after a short pause bridge this gap almost unnoticed.

Step 12: Test the failure of a region

A failover that has never been rehearsed rarely works when it really counts. Simulate the failure of a region by taking its node out of service, and watch how the cluster and DNS react:

docker node update --availability drain swarm-asia
docker node ls
docker service ls
docker node update --availability active swarm-asia

Because the region's services are bound to their node by a placement constraint, they do not move elsewhere but pause; the DNS failover takes care of the region's users. So in this test, check above all whether the health check removes the region from the responses and whether the neighboring region carries the additional load. For a tougher test, cut the node off from the network entirely, for example by stopping WireGuard. Repeat the test after major changes and at least once a quarter.

Data: the hardest part of high availability

Docker Swarm replicates containers, not data. A volume always lives on the node where the container runs. Stateless services such as web frontends and APIs can therefore run in every region without any problems, but for anything that holds data, you need replication of its own.

Replicating databases across continents

Databases come with their own replication, and it is always preferable to shared storage across data centers. Across continents, a proven setup is a primary instance in one region with asynchronous replicas in the other two: for PostgreSQL, for example, streaming replication with a tool such as Patroni for automatic failover, and for MariaDB and MySQL the built-in replication. Each region then answers read requests locally, while writes go to the primary instance. To be honest, asynchronous also means that if the primary region fails, the last few seconds of writes may be missing. If you want to write worldwide and lose nothing, go with a database built for multiple regions, such as CockroachDB or YugabyteDB. Pin the database nodes to their region with a placement constraint so that Swarm never moves them away from their data:

docker service create --name db-asia --constraint node.labels.region==asia ...

Files and uploads

Uploaded files do not belong in a local volume but in S3-compatible object storage with replication to a second region, or in a replicated storage system of your own. Network file systems such as NFS across continents are slow and are themselves a single point of failure.

Sessions and caches

If the application keeps sessions in a container's memory, users lose their login during a switchover. Store sessions in a replicated database or a replicated cache such as Redis, or use signed tokens that every region can verify on its own.

Backups are still mandatory

Replication protects against the loss of a location, but not against mistakes: a record deleted by accident is gone from every region seconds later. That is why regular, tested backups to an independent location are part of every high-availability architecture, as described in the article Backup strategy for servers.

Operations: updates, maintenance and monitoring

Updates region by region

Do not roll out new versions to all regions at once but one after the other, and watch each region for a short while before moving on to the next. That way, a bug that no health check catches reaches one region at most, and the other two keep serving that region's users:

for r in asia us eu; do
  docker service update --image registry.example.com/web:1.1 web-$r || break
  sleep 300
done

If an update fails, Swarm rolls it back automatically thanks to the settings from step 9, and || break ends the loop as soon as the command reports an error. If problems with an update only show up later, roll it back manually with docker service rollback web-asia.

Maintaining a region

If a server needs to be rebooted or updated, take it out of service with docker node update --availability drain and let the DNS failover redirect its users to the neighboring regions beforehand. After the maintenance, bring it back with --availability active. Before moving on to the next manager, wait until docker node ls shows all three as reachable again, so that two managers are never missing at the same time.

Monitoring from the outside

Monitor each region individually and from outside the cluster: reachability of the entry points, health checks of the services, the state of the managers, the database replication lag and the expiration dates of certificates and domains. An alert has to get through even when an entire region goes silent. The article Setting up server monitoring shows how to build this for individual servers.

Distributing secrets securely

Passwords and keys do not belong in environment variables or Compose files but in Docker secrets. They are stored encrypted in the Raft log and delivered only to the services you explicitly assign them to:

printf '%s' 'YOUR_DATABASE_PASSWORD' | docker secret create db_password -
docker service update --secret-add db_password web-eu

Why KernelHost for a swarm across multiple continents

A cluster spanning several continents places different demands on the provider than a single server does. These are the points that matter in practice:

RequirementWhy it mattersAt KernelHost
Locations on multiple continentsThe quorum needs three independent locations, and users want short pathsFrankfurt am Main plus locations in Europe, North America and Asia-Pacific from a single provider
Unlimited trafficWireGuard, the overlay network and database replication generate constant traffic between the continentsUnlimited traffic VPS with no data cap
DDoS protectionEvery entry point is publicly reachable and therefore a targetIncluded at every location, at the core location in Frankfurt am Main with 3.2 Tbps of Arbor real-time filtering, without null-routing
Full root accessWireGuard, the firewall and Docker Engine need full controlOn every KVM root server and dedicated server
Fast provisioningReplacement nodes and test regions should be up in minutesAround 30 seconds in Frankfurt am Main, usually a few minutes at other locations
No contract lock-in per nodeNodes come and go with demandPrePaid, no minimum term, no setup fee
AutomationNew nodes should be created by scriptOrdering and control through the KernelHost API

An overview of all cloud plans with prices, along with a cost comparison against the big cloud providers, is on the Cloud server hosting page.

Common mistakes and how to avoid them

  • Managers at only two locations. If the location with the majority fails, the cluster comes to a standstill. Solution: three locations, split 1-1-1 or 2-2-1.
  • An even number of managers. Four managers do not tolerate more failures than three, but they add coordination overhead. Solution: 3, 5 or 7.
  • Requests travel between continents. A single service address across all regions sends users halfway around the world. Solution: one service and one entry point per region.
  • Swarm ports publicly reachable. Port 2377 and the overlay network never belong on the open internet. Solution: WireGuard only; publicly, only 80, 443 and WireGuard for the other nodes.
  • Forgetting the MTU. Large responses hang, small ones work. Solution: an overlay MTU of 1370 with WireGuard at 1420.
  • Relying on ufw for container ports. Docker bypasses ufw for published ports. Solution: publish only the entry point.
  • A database in a volume without replication. If the region fails, the data is unreachable. Solution: database replication, with placement pinned to the region.
  • Updating all regions at once. A bug then hits every user worldwide. Solution: roll out region by region.
  • A high DNS TTL. With a TTL of one day, the failover only takes effect the next day. Solution: 60 seconds.
  • Replication instead of backups. A mistake gets replicated just like good data. Solution: tested backups at an independent location as well.

In short

  • A Docker Swarm across three continents is designed for 100% uptime: an entire location or continent can fail without the application going down.
  • Nobody can guarantee availability in absolute terms; the remaining risks are DNS, faulty updates, the database and certificates, and there is a countermeasure for each of them.
  • Three managers at three locations are the minimum; two locations are not enough for a fault-tolerant quorum.
  • Every request stays in its region: one service and one entry point per region, plus Geo-DNS with health checks and a short TTL.
  • WireGuard encrypts the cluster traffic, the Swarm ports stay invisible, and the overlay MTU drops to 1370.
  • Swarm replicates containers, not data: databases need their own replication, and backups remain mandatory.
  • KernelHost offers locations in Europe, North America and Asia-Pacific, unlimited traffic, DDoS protection at every location and PrePaid billing with no minimum term.

Frequently asked questions

Can Docker Swarm guarantee 100% uptime?
A Docker Swarm across three continents is designed for 100% uptime, because no single server, data center or continent can stop the application on its own. Even so, nobody can guarantee availability in absolute terms, not even the big cloud providers. The remaining risks are shared dependencies such as DNS, faulty updates, the database and certificates. Health checks with automatic rollback, region-by-region updates, database replication and monitoring protect against them.
How many manager nodes does a highly available Docker Swarm need?
At least three, spread across three independent locations. The managers maintain the cluster state through Raft consensus and need a majority for every change: three managers tolerate one failure, five tolerate two, seven tolerate three. Docker recommends an odd number distributed across at least three zones, with three managers in a 1-1-1 split.
Why are two data centers not enough for Docker Swarm?
Because with two locations, one of them inevitably holds more managers. If exactly that location fails, the majority of the managers is gone, and the cluster can no longer reschedule, compensate for failures or roll out updates. The running containers keep working, but the cluster is unable to act. Only with three locations does the quorum survive the loss of any one data center.
Can Swarm managers be spread across different continents?
Yes. A swarm with one manager each in North America, Europe and Asia survives the loss of an entire continent. The price is slower cluster management, because every change waits for confirmation over long-distance links with 80 to 250 milliseconds of latency. For users this makes no difference as long as every request is answered in its own region, which means one service and one entry point per region.
Which ports does Docker Swarm need?
Between the nodes, Docker Swarm needs port 2377/TCP for cluster management, port 7946/TCP and UDP for node communication and port 4789/UDP for the overlay network. If the overlay network uses the built-in encryption, IP protocol 50 (ESP) must also be allowed. None of these ports belongs on the open internet; the safest option is to run them exclusively through a WireGuard network between the nodes.
Do I need WireGuard, or is the encrypted overlay network enough?
The encrypted overlay network (--opt encrypted) only protects the containers' data traffic and, according to Docker, comes at a noticeable performance cost. WireGuard, on the other hand, encrypts all traffic between the nodes, including management and node communication, and keeps every Swarm port off the internet. For a cluster spanning multiple data centers, we recommend WireGuard with an overlay MTU of 1370 bytes.
How does failover between continents work?
A DNS service with geo-routing and health checks sends each user to the nearest region and checks every 30 to 60 seconds whether that region's entry point responds. If a region fails, the service stops handing out its address and directs users to the nearest healthy region. With a TTL of 60 seconds, the switchover is usually complete after one to two minutes.
How do databases stay available when a location fails?
Through the database's own replication, not through Docker. Swarm replicates containers, not volumes. A proven setup is a primary instance in one region with replicas in the others, for PostgreSQL for example with Patroni for automatic failover. Across continents, replication runs asynchronously, so in an emergency the last few seconds of writes may be missing. If you need to write worldwide without any data loss, use a database built for multiple regions, such as CockroachDB or YugabyteDB.
Docker Swarm or Kubernetes for multiple locations?
Docker Swarm is considerably easier to set up and operate, and it is fully sufficient for many applications. Kubernetes offers more options in automation, scaling and ecosystem, but requires more expertise. Across continents, Kubernetes is usually run as one cluster per region, with the clusters rolled out together via GitOps, whereas a single Swarm cluster can span multiple continents.
Which KernelHost locations are suitable for a swarm across three continents?
KernelHost offers servers in Frankfurt am Main and at further locations in Europe, North America and Asia-Pacific, including three locations in the USA as well as Canada, London, Strasbourg, Warsaw, Helsinki, Singapore, Japan, Sydney and Mumbai. A proven combination for three continents is Frankfurt am Main, the US East Coast and Singapore. All locations are available from a single provider, with DDoS protection and PrePaid billing.
What does a Docker Swarm across three continents cost?
At its core, three servers, one per region, plus a DNS service with health checks. Because WireGuard, the overlay network and database replication generate constant traffic between the locations, plans with unlimited traffic are essential: with many of the big cloud providers, exactly this traffic costs extra per gigabyte. At KernelHost, the unlimited traffic VPS run with no data cap, PrePaid, with no minimum term and no setup fee.

Docker Swarm High availability Multi-region WireGuard Geo-DNS Failover Docker Cloud