Zpět na domů

Docker na VPS: 24 kontejnerů v produkci

Článek rozebírá nasazení produkce 24 Docker kontejnerů na jednom VPS s 6 GB RAM. Jsou zváženy architektonické principy izolace, správa závislostí přes healthcheck, optimalizace spotřeby paměti Elasticsearch a Chrome Headless, bezpečná práce s vzdálenými DB přes SSH tunely a lehký monitoring bez Prometheus.

24 kontejnerů na jednom serveru: technická analýza
Advertisement 728x90

24 kontejnery na jednom VPS: technická architektura vysoké hustoty pro middle/senior DevOps

Klíčový přístup — striktní síťová izolace. Každý projekt je umístěn ve vlastní Docker síti (bridge), což vylučuje vzájemné závislosti a minimalizuje plochu útoku. Společná síť shared se používá pouze pro systémové služby (například monitoring nebo společný Redis). Interní porty (9200, 8088, 9222) jsou dostupné výhradně přes 127.0.0.1, externí přístup je zakázán na úrovni iptables a konfigurace nginx.

Odolnost je zajištěna prostřednictvím healthcheck závislostí v docker-compose.yml. Například PHP služby v projektu EdTech nezačínají, dokud SSH tunel k vzdálené databázi neprojde kontrolou nc -z 127.0.0.1 3306. To zaručuje, že aplikace se nebude snažit připojit k nedostupné databázi a nezablokuje frontu chybami.

Sledovatelnost je postavena bez Prometheus/Grafana — kvůli omezení RAM. Místo toho se používá bash skript, který se spouští každých 15 minut:

Google AdInline article slot
  • Kontrola HTTP stavů veřejných endpointů (/health, /webhook/advert)
  • Hledání nemocných kontejnerů prostřednictvím docker ps --filter "health=unhealthy"
  • Monitoring disku a využití swapu
  • Upozornění jsou odesílána do Telegram chatu pomocí curl k Bot API

To poskytuje minimální, ale dostatečnou viditelnost pro jednoho administrátora.

Kritické komponenty: Elasticsearch, Chrome Headless a SSH tunely

Tři komponenty určují hranice výkonu VPS:

  • Elasticsearch 8.12.2 spotřebovává 1,47 GB RAM. Bez explicitního memory: 2g v deploy.resources.limits začne JVM vytláčet sousední procesy do swapu, což způsobuje nestabilitu. Pro index o cca 50 tisících dokumentech a protokolování je to optimální rovnováha mezi funkcionalitou a zatížením. Alternativa — Meilisearch — vyžaduje migraci stávajících indexů a změnu klientského kódu, což je v současné fázi hodnoceno jako náročná a málo rentabilní úloha.
  • Chrome Headless (zenika/alpine-chrome) zabírá 636 MB RAM, i když se používá jen jednou za hodinu pro scrapování JS renderingu. Spuštění on-demand prostřednictvím docker run --rm by ušetřilo paměť, ale přidalo by 5–10 sekund zpoždění na každý volání. Pro služby s přísnými SLA je to nepřijatelné; zde je to však přijatelný kompromis.
  • SSH tunely jsou implementovány v samostatných alpine kontejnerech s autossh. Zajišťují bezpečný přístup k MySQL na shared hostingu bez otevírání portů ven. Konfigurace zahrnuje ServerAliveInterval=30, AUTOSSH_GATETIME=0 a healthcheck prostřednictvím nc. Toto řešení funguje se všemi hostingy podporujícími SSH a plně nahrazuje placené managed databáze.

Optimalizace Nginx a PHP: snížení latence na milisekundy

Nginx je nastaven pouze pro webhooks a API — žádné statické soubory kromě /health. Klíčová optimalizace — vyjmutí zpracování Telegram webhooků do samostatného PHP souboru (webhook-advert.php), který nenabíhá Laravel bootstrap. To zkracuje čas odezvy z 80–120 ms na 15–25 ms, což je kritické při masivních webhook voláních od Telegram API (maximální timeout — 60 sekund).

Google AdInline article slot

Konfigurace také zahrnuje:

  • Povinný přesměrování HTTP → HTTPS
  • Odmítnutí zpracování jakýchkoli cest kromě /health, /webhook/ a /api/telegram/
  • Zvýšený fastcgi_read_timeout na 120 sekund pro dlouhotrvající úkoly
  • Použití realpath_root pro správné zpracování index.php

SSL a bezpečnost: tři strategie na jednom hostu

SSL terminace je organizována hybridně:

  • getssl + Let's Encrypt — pro domény, kde je potřeba end-to-end šifrování a není Cloudflare
  • Cloudflare Proxy — pro většinu domén: SSL terminuje na edge, provoz do VPS probíhá přes HTTP, ale je chráněn IP filtrací (jen Cloudflare ASN)
  • Ruční aktualizace — dočasná opatření pro AI backend, který je v procesu automatizace prostřednictvím Caddy

Nastavení Cloudflare zahrnuje povinné zapnutí Always Use HTTPS, WAF a Rate Limiting (100 požadavků/min na IP), což kompenzuje absence WAF na straně VPS.

Google AdInline article slot

Co je důležité

  • Striktní síťová izolace prostřednictvím samostatných Docker sítí zabraňuje kaskádovým selháním a zjednodušuje bezpečnostní audit.
  • Healthcheck závislosti v docker-compose zaručují, že služby startují pouze po připravenosti svých závislostí (například SSH tunelu k databázi).
  • Elasticsearch vyžaduje striktní memory limit (2 GB), jinak JVM vytláčí sousední kontejnery do swapu, což způsobuje OOM-killer.
  • Chrome Headless je vhodné držet v režimu always-on při nízké frekvenci použití, pokud je zpoždění spuštění kritické pro business logiku.
  • Bash monitoring s Telegram alerty — funkční náhrada Prometheus/Grafana při nedostatku RAM, za předpokladu jasně definovaných SLO.

— Editorial Team

Advertisement 728x90

Číst dál