Přeskočit na obsah

Dokploy (Docker)

Web je server-rendered pomocí Astro Node adaptéru a Kafe-CMS, takže se nasazuje jako dlouhoběžící Node server, nikoli statické soubory. Repozitář přináší vícefázový Dockerfile, který sestaví samostatný server (dist/server/entry.mjs).

  1. Pushněte repozitář na GitHub.
  2. V Dokploy vytvořte Application z repozitáře pomocí Dockerfile buildu.
  3. Připojte perzistentní svazek na /app/data. Ten drží SQLite databázi (kafecms.db) a všechny lokální nahrané soubory, takže obsah přežije redeploye.
  4. Nastavte proměnné prostředí (viz Proměnné prostředí): SITE_URL, S3_* přihlašovací údaje Cloudflare R2 a případné volitelné analytické klíče.
  5. Vystavte port 4321 a nasměrujte na službu svou doménu.
  6. Nasaďte. Na čerstvém svazku entrypoint automaticky naseeduje obsah (níže).

V produkci se média ukládají do Cloudflare R2 přes jeho S3-kompatibilní API. Vytvořte R2 bucket a S3 API token, poté nastavte S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID a S3_SECRET_ACCESS_KEY. Pokud je S3_BUCKET nenastavený, Kafe-CMS spadne zpět na úložiště v lokálním souborovém systému pod ./data/uploads.

Uploady jdou PUT přímo do R2 z prohlížeče přes presigned URL, takže bucket potřebuje CORS politiku povolující origin vašeho webu (GET, PUT, HEAD). Bucket může zůstat privátní — Kafe-CMS servíruje média přes vlastní proxy routu (/kafecms/api/media/file/<key>), která streamuje objekty z R2, takže URL vždy vypadají same-origin a S3_PUBLIC_URL není potřeba. Viz Proměnné prostředí → Úložiště médií pro přesnou CORS politiku a detaily.

Astro Node adaptér servíruje HTML, CSS a JS nekomprimované — nemá vestavěnou kompresi. To samo o sobě sráží Lighthouse Performance dolů (~53 KB stylesheet se posílá celý, což nafukuje FCP/LCP), i když je server rychlý. Komprimujte na Traefik reverzní proxy, kterou Dokploy už provozuje.

V Dokploy: otevřete aplikaci → Advanced → Traefik a přidejte middleware compress, poté ho připojte k routeru aplikace. Dynamická konfigurace vypadá takto:

http:
middlewares:
site-compress:
compress:
# Nekomprimujte Server-Sent Events — živý náhled Kafe-CMS je používá.
excludedContentTypes:
- text/event-stream
routers:
# Přidejte middleware k existujícímu routeru, který Dokploy pro tuto aplikaci vygeneroval:
<existing-router-name>:
middlewares:
- site-compress

Po uložení ověřte pomocí curl -sI -H "Accept-Encoding: br,gzip" https://your-domain/ — odpověď by měla obsahovat content-encoding: br (nebo gzip). To typicky posune Lighthouse Performance z ~90 na ~100, protože render-blocking CSS a JS se teď přenášejí za zlomek své velikosti.

Veřejné marketingové stránky posílají téměř žádný JavaScript (interaktivní části jsou prosté Astro + drobné inline skripty), takže komprese je hlavní zbývající páka. Těžké React bundly, které můžete vidět pod /_astro, patří administraci Kafe-CMS a načítají se jen na routách /kafecms.

Aplikace přináší middleware (src/middleware/security-headers.ts), který posílá skutečné bezpečnostní hlavičky na veřejném webu: striktní Content-Security-Policy, plus Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy a Cross-Origin-Opener-Policy. CSP je bez nonce a bez 'unsafe-inline' pro skripty — bufferuje každou HTML odpověď a počítá SHA-256 hash pro každý inline <script>, který je skutečně vyemitovaný (dark-mode bootstrap, analytické snippety, …) a automaticky whitelistuje externí skriptové originy, takže zůstává striktní bez ruční údržby. Administrace Kafe-CMS (/kafecms) je ponechána vlastní CSP. Nastavením DISABLE_SECURITY_HEADERS=1 middleware vypnete (např. pokud váš edge tyto hlavičky už nastavuje).

Poznámka k pokrytí: Astro middleware běží jen pro server-rendered routy. Prerenderované Starlight stránky /docs, 404 a statické assety pod /_astro jsou servírovány přímo Node adaptérem a middleware obcházejí. Pro plošné pokrytí (včetně těchto rout) nastavte hlavičky i na vrstvě Traefik — to je doporučené produkční nastavení:

http:
middlewares:
site-headers:
headers:
stsSeconds: 63072000
stsIncludeSubdomains: true
stsPreload: true
contentTypeNosniff: true
referrerPolicy: strict-origin-when-cross-origin
frameDeny: true
permissionsPolicy: "camera=(), microphone=(), geolocation=(), browsing-topics=()"
routers:
<existing-router-name>:
middlewares:
- site-compress
- site-headers

CSP per-aplikaci ponechte middlewaru (liší se stránku od stránky), nebo zde replikujte statickou CSP, pokud chcete, aby proxy vlastnila vše.

SQLite databáze je runtime stav a necommituje se do gitu — žije na svazku /app/data. Při nasazení:

  • Server spouští schema migrace automaticky při prvním požadavku, čímž vytvoří databázi a tabulky na svazku.
  • docker-entrypoint.sh kontejneru spustí kafecms seed ze seed/seed.json jen tehdy, když ještě žádná databáze neexistuje (čerstvý svazek), takže první deploy naběhne naplněný a redeploye nikdy nepřepíšou vaše data.

Pro ruční seedování nebo re-seedování (např. mimo Docker):

Terminal window
pnpm exec kafecms seed --database data/kafecms.db --uploads-dir data/uploads

Poté se obsah upravuje přes administraci na /kafecms/admin (při první návštěvě vytvořte účet vlastníka) a nevyžaduje žádný redeploy.

Terminal window
docker build -t astro-kafecms .
docker run --rm -p 4321:4321 -v "$PWD/data:/app/data" astro-kafecms