diff --git a/Dockerfile b/Dockerfile index 0f0e4e5..9cbc51a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -# Stage 1: Build Vite SPA +# Stage 1: Vite SPA build FROM node:22-alpine AS build WORKDIR /app COPY package*.json ./ @@ -6,9 +6,21 @@ RUN npm ci COPY . . RUN npm run build -# Stage 2: Production Nginx Server -FROM nginx:alpine +# Stage 2: nginx (frontend) + node (canlı veri backend) tek container'da +FROM node:22-alpine +RUN apk add --no-cache nginx + +# Frontend COPY --from=build /app/dist /usr/share/nginx/html -COPY --from=build /app/nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=build /app/nginx.conf /etc/nginx/http.d/default.conf + +# Backend (yalnızca Node builtin'leri kullanır — npm bağımlılığı yok) +WORKDIR /app +COPY --from=build /app/server ./server + +# Başlangıç: Node backend'i (3001) arka planda + nginx ön planda +RUN printf '#!/bin/sh\nset -e\nnode /app/server/index.js &\nexec nginx -g "daemon off;"\n' > /start.sh \ + && chmod +x /start.sh + EXPOSE 80 -CMD ["nginx", "-g", "daemon off;"] +CMD ["/start.sh"] diff --git a/nginx.conf b/nginx.conf index b9c37aa..ae40c3e 100644 --- a/nginx.conf +++ b/nginx.conf @@ -5,10 +5,19 @@ server { root /usr/share/nginx/html; index index.html; - # Ensure proper MIME types for JavaScript, CSS, etc. include /etc/nginx/mime.types; - # Serve static assets directly + # Canlı veri backend'i (aynı container'da Node, port 3001) + location /api/ { + proxy_pass http://127.0.0.1:3001; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_read_timeout 60s; + proxy_connect_timeout 10s; + } + + # Statik varlıklar location /assets/ { root /usr/share/nginx/html; try_files $uri =404; @@ -16,7 +25,7 @@ server { add_header Cache-Control "public, no-transform"; } - # SPA routing fallback for app routes + # SPA yönlendirmesi location / { try_files $uri $uri/ /index.html; } diff --git a/server/dt-store.mjs b/server/dt-store.mjs index 5c3105e..ef44dde 100644 --- a/server/dt-store.mjs +++ b/server/dt-store.mjs @@ -3,11 +3,19 @@ * Veritabanı yoksa (worker hiç koşmadıysa) sessizce boş liste döner. */ -import { DatabaseSync } from 'node:sqlite'; import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; +// node:sqlite bazı Node sürümlerinde deneysel/flag'li. Yoksa DT devre dışı kalır, +// ilan.gov.tr canlı verisi yine de çalışır. +let DatabaseSync = null; +try { + ({ DatabaseSync } = await import('node:sqlite')); +} catch { + console.warn('[dt-store] node:sqlite yok — doğrudan temin devre dışı (açık ihaleler etkilenmez)'); +} + const __dirname = path.dirname(fileURLToPath(import.meta.url)); const DB_PATH = path.join(__dirname, 'data', 'dt.sqlite'); @@ -92,7 +100,7 @@ function mapDtRow(row) { } export function readDtTenders(limit = 300) { - if (!fs.existsSync(DB_PATH)) return { tenders: [], totalCount: 0, available: false }; + if (!DatabaseSync || !fs.existsSync(DB_PATH)) return { tenders: [], totalCount: 0, available: false }; const db = new DatabaseSync(DB_PATH, { readOnly: true }); try { const total = db.prepare('SELECT COUNT(*) c FROM dt_tenders').get().c;