All posts

60+ Docker containers on one server: the architecture that runs TRUJO

2026-05-168 min· Juan José Trujillo Cardozo

We run 60+ Docker containers on a single server. Not a Kubernetes cluster. Not AWS. A VPS in Germany that costs less than what many companies pay for a single cloud service. Inside run the production services that keep our clients online: the POS, the WhatsApp API, the biometric system, electronic invoicing, monitoring.

The obvious question: isn't that excessive for a small company? Maybe. But the real thesis is different: infrastructure does not have to be expensive to be professional. It has to be automated, monitored, and documented. We achieve that with a small senior team and aggressive automation, not an army of people.

## Architecture: simple but disciplined

Docker Compose is the base. Each service has its own compose file in its own directory. The POS in one place, the WhatsApp API in another, the biometric system in another. If one fails, the others never notice.

Everything routes through Nginx Proxy Manager as reverse proxy. Each domain hits NPM on port 80 or 443, and NPM routes it to the correct container inside the internal network. No container exposes ports directly except NPM. Databases live on a separate network that never touches the internet.

[CODE:bash] # Each stack updates, restarts, or removes without touching the rest docker compose -f stacks/pos/compose.yml up -d docker network ls # trujonet, trujo-internal, ai-callcenter-net [/CODE]

This is not elegant. It is practical. And practicality is what survives six months without drama.

## Autonomous AI monitoring every 60 seconds

An infrastructure agent scans the whole network every 60 seconds: down containers, missing healthchecks, abnormal disk usage, unresponsive services. If a container is not on the protected list, it restarts automatically. If it is protected, a Telegram alert arrives — not a plain "container X is down," but log analysis, probable cause, and a suggested action. It uses a local AI engine with cloud fallback.

A security agent watches fail2ban in real time. Brute-force attempts against SSH or the proxy trigger an alert with the IP, country, and attempt count. All 24/7, no manual intervention.

## Backups and disaster recovery

Daily at 2am a script backs up the databases (PostgreSQL, MariaDB, SQLite), compressed, 30-day local retention. At 4am another script syncs them offsite to Cloudflare R2. Full rebuild from zero takes about 2 hours: compose files in Git, data in backups, secrets in chmod-600 .env files. We tested it. Knowing it works is what lets you sleep.

## What we learned

Aggressive automation is the real multiplier. SRE discipline: if it is not measured, it does not exist. Infrastructure as code: nothing configured by hand, because hand-config gets forgotten and never reproduces.

The transparency of all this lives at /trust, with a public deployment map and verifiable telemetry. We do not ask you to believe us — we ask you to check.

Write to [email protected] or WhatsApp wa.me/573172946935.