From e0e263b6bb5db17221326b988217f2514619554b Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sun, 1 Mar 2026 20:18:20 +0000 Subject: [PATCH] Add Dockerfile and nginx config for Coolify deployment Multi-stage build: Node.js 22 for Astro build, nginx:alpine for serving. Includes gzip, security headers, and immutable cache for _astro/ assets. --- .dockerignore | 7 ++++++ Dockerfile | 13 ++++++++++ nginx.conf | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 nginx.conf diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ff96be3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +node_modules +dist +.git +.env* +.DS_Store +*.md +!README.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9da4bd9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +# Stage 1: Build +FROM node:22-alpine AS build +WORKDIR /app +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npm run build + +# Stage 2: Serve +FROM nginx:alpine +COPY --from=build /app/dist /usr/share/nginx/html +COPY nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 80 diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..3e5ce1d --- /dev/null +++ b/nginx.conf @@ -0,0 +1,67 @@ +server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_min_length 256; + gzip_types + text/plain + text/css + text/javascript + application/javascript + application/json + application/xml + image/svg+xml + font/woff2; + + # Astro hashed assets — immutable cache + location /_astro/ { + expires 1y; + add_header Cache-Control "public, immutable"; + access_log off; + } + + # Static files + location ~* \.(ico|svg|png|jpg|jpeg|webp|gif|woff2?|ttf|eot)$ { + expires 30d; + add_header Cache-Control "public"; + access_log off; + } + + # CSS/JS + location ~* \.(css|js)$ { + expires 7d; + add_header Cache-Control "public"; + } + + # Main location — clean URLs (Astro generates /page/index.html) + location / { + try_files $uri $uri/ $uri.html /index.html =404; + } + + # Deny hidden files + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + + # Custom error pages + error_page 404 /404.html; + location = /404.html { + internal; + } +}