diff --git a/Dockerfile b/Dockerfile index 99fb2ae..136a800 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,26 +3,29 @@ ARG NODE_VERSION=20.15.0 FROM node:${NODE_VERSION}-alpine AS build WORKDIR /app -# Install deps first for better caching +# Install deps with cache leverage COPY package*.json ./ RUN npm ci || npm install # Build COPY . . ENV NODE_ENV=production -# Limit Node heap during build to avoid OOM on small builders ENV NODE_OPTIONS=--max-old-space-size=512 RUN npm run build # ---- Runtime (Nginx) ---- FROM nginx:1.27-alpine AS runtime +# Install curl for healthcheck +RUN apk add --no-cache curl # Remove default site content RUN rm -rf /usr/share/nginx/html/* -# SPA config (history fallback) +# SPA config COPY docker/nginx.conf /etc/nginx/conf.d/default.conf # Static assets COPY --from=build /app/dist /usr/share/nginx/html + EXPOSE 80 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ - CMD wget -qO- http://localhost/ >/dev/null 2>&1 || exit 1 + CMD curl -fsS http://localhost/ >/dev/null || exit 1 + CMD ["nginx", "-g", "daemon off;"] diff --git a/README.md b/README.md index 93ea358..58ca0e2 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,12 @@ -# Reading Goal App (Dockerized) +# Reading Goal App (Dockerized — healthcheck fix) -React + Vite + Tailwind. Dates use **DD/MM/YYYY** and the calendar week starts on **Monday**. -Includes a multi-stage Dockerfile: Node build → Nginx runtime with SPA fallback. +This bundle installs `curl` in the Nginx runtime and uses a curl-based HEALTHCHECK. +- Internal port: **80** +- SPA fallback via Nginx +- Build heap capped to avoid OOM -## Local Dev -```bash -npm install -npm run dev -``` - -## Production Build (local) -```bash -npm run build -npm run preview -``` - -## Docker (build locally) +## Build & Run ```bash docker build -t reading-goal-app:latest . docker run -d --name reading-goal-app -p 8080:80 --restart unless-stopped reading-goal-app:latest -# Open http://localhost:8080 ``` - -## Deploy in Coolify -- Deployment Type: **Dockerfile** -- Dockerfile path: `Dockerfile` -- **Internal Port**: `80` (Nginx) -- No extra start command needed. - -The multi-stage image builds the app (`vite build`) and serves static files via Nginx with history API fallback. diff --git a/docker/nginx.conf b/docker/nginx.conf index 3a2f3e9..c24ac42 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -1,15 +1,14 @@ server { listen 80; + listen [::]:80; server_name _; root /usr/share/nginx/html; index index.html; - # Serve files if they exist, else fallback to index.html (SPA) location / { try_files $uri $uri/ /index.html; } - # Static assets (cache-friendly) location ~* \.(?:js|css|png|jpg|jpeg|gif|svg|ico|woff2?)$ { expires 30d; add_header Cache-Control "public, immutable";