feat: Docker setup voor Coolify deploy (nginx + SPA fallback)

Multi-stage Dockerfile: node bouwt Vite output, nginx serveert dist/.
nginx.conf: SPA try_files fallback, gzip, cache headers voor /assets/.
.dockerignore: houdt build context schoon (node_modules, dist, .git).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Frank Meeuwsen 2026-04-17 07:54:43 +02:00
parent d43ce49aa7
commit 6a2e08d9f0
3 changed files with 69 additions and 0 deletions

18
.dockerignore Normal file
View file

@ -0,0 +1,18 @@
node_modules
dist
.git
.gitignore
.env
.env.*
.vscode
.claude
*.log
npm-debug.log*
.DS_Store
README.md
PRD.md
LOGBOEK.md
preflight.sh
content
.dashboard.yml
.specstory

20
Dockerfile Normal file
View file

@ -0,0 +1,20 @@
# Multi-stage build voor de Claude Code Workshop sales page
# Stage 1: Node.js bouwt de Vite production bundle
# Stage 2: Nginx serveert de statische output
FROM node:20-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

31
nginx.conf Normal file
View file

@ -0,0 +1,31 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Gzip voor tekstuele assets
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
# Cache hashed assets uit de Vite build (bestandsnaam bevat hash)
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# SPA fallback: stuur alle onbekende routes naar index.html
# zodat React Router de routes /bedankt, /inschrijven etc. afhandelt
location / {
try_files $uri $uri/ /index.html;
}
# index.html zelf nooit cachen, anders zie je geen nieuwe deploys
location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
expires 0;
}
}