diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f97574a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,63 @@ +# Dependencias y builds (se generan dentro del contenedor) +node_modules +**/node_modules +dist +**/dist + +# Variables de entorno (NUNCA en imágenes) +.env +.env.* +**/.env +**/.env.* +!**/.env.example + +# Git +.git +.gitignore + +# Editor / SO +.vscode +.idea +.DS_Store +*.swp +*.swo + +# Logs +*.log +logs + +# Documentación y archivos de planificación que no necesita el build +*.md +!README.md +architecture +directivas +skills +.agents +.claude +.codebuddy +.commandcode +.continue +.crush +.factory +.goose +.kilocode +.kiro +.mcpjam +.mux +.neovate +.openhands +.pi +.qoder +.qwen +.roo +.tmp +.trae +.windsurf +.zencoder +findings.md +gemini.md +progress.md +task_plan.md + +# Imágenes de diseño en raíz +*.png diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile new file mode 100644 index 0000000..51a5aa3 --- /dev/null +++ b/apps/api/Dockerfile @@ -0,0 +1,38 @@ +# syntax=docker/dockerfile:1 + +# ───── Stage 1: build ───── +FROM node:22-alpine AS builder +WORKDIR /repo +RUN corepack enable + +# Manifiestos primero (para cachear pnpm install si no cambian deps) +COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./ +COPY packages/shared/package.json ./packages/shared/ +COPY apps/api/package.json ./apps/api/ + +RUN pnpm install --frozen-lockfile + +# Código fuente +COPY packages/shared ./packages/shared +COPY apps/api ./apps/api + +# Compila TypeScript del api +RUN pnpm --filter @naturcalabacera/api build + +# Carpeta de despliegue self-contained con node_modules de producción +RUN pnpm --filter @naturcalabacera/api deploy --prod /out + +# Copia plantillas HTML al dist (tsc no las copia) +RUN cp -r apps/api/src/templates /out/dist/templates + +# ───── Stage 2: runtime ───── +FROM node:22-alpine +WORKDIR /app +ENV NODE_ENV=production + +COPY --from=builder /out/dist ./dist +COPY --from=builder /out/node_modules ./node_modules +COPY --from=builder /out/package.json ./package.json + +EXPOSE 3001 +CMD ["node", "dist/index.js"] diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile new file mode 100644 index 0000000..5daaeb4 --- /dev/null +++ b/apps/web/Dockerfile @@ -0,0 +1,52 @@ +# syntax=docker/dockerfile:1 + +# ───── Stage 1: build ───── +FROM node:22-alpine AS builder +WORKDIR /repo +RUN corepack enable + +COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./ +COPY packages/shared/package.json ./packages/shared/ +COPY apps/web/package.json ./apps/web/ + +RUN pnpm install --frozen-lockfile + +COPY packages/shared ./packages/shared +COPY apps/web ./apps/web + +# Variables públicas inyectadas en el bundle por Vite (build-time) +ARG VITE_SUPABASE_URL +ARG VITE_SUPABASE_ANON_KEY +ARG VITE_SUPABASE_SCHEMA +ARG VITE_API_URL +ENV VITE_SUPABASE_URL=$VITE_SUPABASE_URL +ENV VITE_SUPABASE_ANON_KEY=$VITE_SUPABASE_ANON_KEY +ENV VITE_SUPABASE_SCHEMA=$VITE_SUPABASE_SCHEMA +ENV VITE_API_URL=$VITE_API_URL + +RUN pnpm --filter @naturcalabacera/web build + +# ───── Stage 2: runtime (Nginx sirviendo SPA) ───── +FROM nginx:alpine +COPY --from=builder /repo/apps/web/dist /usr/share/nginx/html + +# Config SPA: cualquier ruta cae en index.html (React Router friendly) +RUN printf 'server {\n\ + listen 80;\n\ + server_name _;\n\ + root /usr/share/nginx/html;\n\ + index index.html;\n\ +\n\ + location / {\n\ + try_files $uri $uri/ /index.html;\n\ + }\n\ +\n\ + # Cache largo para assets con hash\n\ + location /assets/ {\n\ + expires 1y;\n\ + add_header Cache-Control "public, immutable";\n\ + }\n\ +}\n' > /etc/nginx/conf.d/default.conf + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/apps/web/index.html b/apps/web/index.html index eac8330..3aeb28d 100644 --- a/apps/web/index.html +++ b/apps/web/index.html @@ -2,9 +2,10 @@
- + + -
+