diff --git a/Dockerfile b/Dockerfile index a1aebf1..43bdb65 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,20 +10,10 @@ WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci -# Copy source +# Copy source and build — no VITE_* args needed at build time. +# Supabase keys are injected at runtime via docker/entrypoint.sh → window.__ENV__ COPY . . - -# VITE_* vars are Supabase public keys — safe for browser, baked into bundle at build time. -# Using ARG only (no ENV) so values don't persist as image-layer env vars. -ARG VITE_SUPABASE_URL -ARG VITE_SUPABASE_ANON_KEY -ARG VITE_SUPABASE_PUBLISHABLE_KEY - -# Pass vars inline so they're scoped to this RUN layer only -RUN VITE_SUPABASE_URL="$VITE_SUPABASE_URL" \ - VITE_SUPABASE_ANON_KEY="$VITE_SUPABASE_ANON_KEY" \ - VITE_SUPABASE_PUBLISHABLE_KEY="$VITE_SUPABASE_PUBLISHABLE_KEY" \ - npm run build +RUN npm run build # ============================================================ # Stage 2 — Serve @@ -37,6 +27,10 @@ COPY nginx.conf /etc/nginx/conf.d/default.conf # Copy built static files from builder COPY --from=builder /app/dist /usr/share/nginx/html +# Entrypoint generates env.js from runtime env vars before starting nginx +COPY docker/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + EXPOSE 80 -CMD ["nginx", "-g", "daemon off;"] +CMD ["/entrypoint.sh"] diff --git a/docker-compose.yml b/docker-compose.yml index 4159f30..07ea7e1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,11 +3,11 @@ services: build: context: . dockerfile: Dockerfile - args: - VITE_SUPABASE_URL: ${VITE_SUPABASE_URL} - VITE_SUPABASE_ANON_KEY: ${VITE_SUPABASE_ANON_KEY} - VITE_SUPABASE_PUBLISHABLE_KEY: ${VITE_SUPABASE_PUBLISHABLE_KEY} image: renolation/english-toeic:latest + environment: + - VITE_SUPABASE_URL=${VITE_SUPABASE_URL} + - VITE_SUPABASE_ANON_KEY=${VITE_SUPABASE_ANON_KEY} + - VITE_SUPABASE_PUBLISHABLE_KEY=${VITE_SUPABASE_PUBLISHABLE_KEY} ports: - "${APP_PORT:-3000}:80" restart: unless-stopped diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 0000000..d637cf1 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# Generate runtime env.js from container environment variables +cat > /usr/share/nginx/html/env.js < + EnglishAI — Luyện TOEIC thông minh diff --git a/nginx.conf b/nginx.conf index 02184b8..8f6f2d0 100644 --- a/nginx.conf +++ b/nginx.conf @@ -22,6 +22,7 @@ server { # Health check endpoint location /health { + access_log off; return 200 "ok"; add_header Content-Type text/plain; } diff --git a/public/env.js b/public/env.js new file mode 100644 index 0000000..e73303b --- /dev/null +++ b/public/env.js @@ -0,0 +1 @@ +window.__ENV__ = {}; diff --git a/src/hooks/use-writing-check.ts b/src/hooks/use-writing-check.ts index ede0746..33c06ff 100644 --- a/src/hooks/use-writing-check.ts +++ b/src/hooks/use-writing-check.ts @@ -114,7 +114,7 @@ export function useWritingCheck() { const feedback = await callEdgeFunction(content, onChunk) if (user) { - saveWritingSubmission(user.id, content, feedback) + await saveWritingSubmission(user.id, content, feedback) queryClient.invalidateQueries({ queryKey: ["writing-history"] }) } else { recordWritingCheckUsage() diff --git a/src/lib/supabase.ts b/src/lib/supabase.ts index fd1f40a..e5a749b 100644 --- a/src/lib/supabase.ts +++ b/src/lib/supabase.ts @@ -1,8 +1,15 @@ import { createClient } from "@supabase/supabase-js" -const supabaseUrl = import.meta.env.VITE_SUPABASE_URL -// Supports both key name conventions +// Runtime env (injected by docker/entrypoint.sh) takes priority over build-time vars +const runtimeEnv = (window as unknown as { __ENV__?: Record }).__ENV__ ?? {} + +const supabaseUrl = + runtimeEnv.VITE_SUPABASE_URL || + import.meta.env.VITE_SUPABASE_URL + const supabaseAnonKey = + runtimeEnv.VITE_SUPABASE_ANON_KEY || + runtimeEnv.VITE_SUPABASE_PUBLISHABLE_KEY || import.meta.env.VITE_SUPABASE_ANON_KEY || import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY