From 81924222639bf3f92196e8587329c24df1a00600 Mon Sep 17 00:00:00 2001 From: RaymondVerhoef Date: Mon, 11 May 2026 20:30:54 +0200 Subject: [PATCH] feat: add production docker-compose configuration and deployment documentation for Portainer integration --- DEPLOYMENT_GUIDE.md | 133 ++++++++++++++++++++++++++++++++++++++++ docker-compose.prod.yml | 37 +++++++++++ 2 files changed, 170 insertions(+) create mode 100644 DEPLOYMENT_GUIDE.md create mode 100644 docker-compose.prod.yml diff --git a/DEPLOYMENT_GUIDE.md b/DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000..36e3866 --- /dev/null +++ b/DEPLOYMENT_GUIDE.md @@ -0,0 +1,133 @@ +# 🎯 Overdrachtsdocument – Productie-deployment van **Respellion Learning Platform** met Portainer + +> **Doel** – Dit document geeft een *complete* handleiding zodat een ontwikkelaar of AI-agent de Respellion Learning Platform applicatie kan bouwen, configureren en in productie draaien op een Hetzner-VPS via Portainer. + +--- + +## 1. Project-structuur + +``` +learning-platform/ +│ +├─ Dockerfile # Productie Dockerfile (Nginx + React/Vite) +├─ nginx.conf # Nginx configuratie voor Anthropic API proxy +├─ docker-compose.prod.yml # Productie-compose configuratie (Caddy SSL + Frontend) +└─ src/ # React frontend broncode +``` + +> **Opmerking**: Deze applicatie is een 100% frontend applicatie ("Single Page Application"). De interne state wordt opgeslagen in `localStorage`. Er is **geen externe backend of database (zoals Postgres)** nodig. De enige netwerk calls gaan via de interne Nginx proxy direct naar de Anthropic API. + +--- + +## 2. Kernbestanden – inhoud & rationale + +### 2.1 `docker-compose.prod.yml` + +```yaml +services: + frontend: + build: . + restart: always + expose: + - "80" + + caddy: + image: caddy:2-alpine + restart: always + ports: + - "80:80" + - "443:443" + environment: + - DOMAIN_NAME=${DOMAIN_NAME} + entrypoint: + - /bin/sh + - -c + - | + # Build Caddyfile on container start + CLEAN_DOMAIN=$(printf '%s' "$DOMAIN_NAME" | tr -d ';') + cat > /etc/caddy/Caddyfile </learning-platform.git` | +| **3** | **Compose path** = `docker-compose.prod.yml` | Zorg dat dit exact overeenkomt met de bestandsnaam in de repo. | +| **4** | **Environment variables** toevoegen | Voeg `DOMAIN_NAME` toe. | +| **5** | **Deploy the stack** | Portainer start de applicatie en Caddy haalt direct het SSL certificaat op (max. 60 sec). | +| **6** | **Controle** | Surf naar `https://jouw-domein.nl`. Je zou de Respellion inlogscherm moeten zien. | + +### Handmatige Force-Rebuild + +Wanneer de repo is geüpdatet en je wil de nieuwe versie afdwingen via command-line: + +```bash +docker compose -f docker-compose.prod.yml up -d --build --no-cache +``` + +--- + +## 5. Veelvoorkomende valkuilen & Fixes + +| Symptom | Oorzaak | Oplossing | +|---------|---------|-----------| +| **SSL Error / ERR_CONNECTION_REFUSED** | DNS is nog niet actief of poort 443 staat dicht in je firewall (Hetzner). | Check Hetzner Cloud Console en open TCP poort 80 & 443 in de Inbound Firewall. | +| **Anthropic API Werkt Niet** | Foute key of Nginx proxy mist configuratie. | Open de app, ga naar Admin -> Settings en vul je Anthropic Key in. Controleer ook of `nginx.conf` correct wordt ingeladen in Nginx. | +| **Witte pagina na deploy** | Oude Docker image wordt gebruikt. | Doe een force-rebuild (`--build --no-cache`) in Portainer of via de console. | + +--- + +## 6. Checklist voor een nieuwe implementatie + +- [ ] Repository up-to-date en gepusht naar `main`. +- [ ] `docker-compose.prod.yml` is gedefinieerd in Portainer. +- [ ] Environment variable `DOMAIN_NAME` is correct ingesteld. +- [ ] DNS A-Record staat op de juiste server. +- [ ] Na eerste inlog: Open "Admin" -> "Settings" en voeg de Anthropic API Key toe, klik op Opslaan. diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..e98ea7e --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,37 @@ +services: + frontend: + build: . + restart: always + expose: + - "80" + + caddy: + image: caddy:2-alpine + restart: always + ports: + - "80:80" + - "443:443" + environment: + - DOMAIN_NAME=${DOMAIN_NAME} + entrypoint: + - /bin/sh + - -c + - | + # Build Caddyfile on container start + CLEAN_DOMAIN=$(printf '%s' "$DOMAIN_NAME" | tr -d ';') + cat > /etc/caddy/Caddyfile <