`VOLUME /app/data` hacía que Docker fabricara un volumen anónimo en cada arranque, y Coolify los purga al recrear el contenedor. Cada despliegue estrenaba una base vacía que `ensureSeed()` volvía a sembrar: se perdían las citas, los clientes y todo lo configurado desde Ajustes, en silencio y sin error. Verificado en el host: el volumen montado era 991d42df… y el día anterior era 3cff8c0d…, y no queda ningún volumen huérfano con agendapro.db — los anteriores fueron destruidos. La base se creaba un minuto después del contenedor. La persistencia la aporta ahora un volumen con nombre declarado como Persistent Storage en Coolify y montado en /app/data, precargado con un snapshot consistente de la base actual (155 citas, 15 clientes, 8 usuarios, integrity_check ok). Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
62 lines
2.4 KiB
Docker
62 lines
2.4 KiB
Docker
# ---- Build frontend ----
|
|
FROM node:22-slim AS web-build
|
|
WORKDIR /app
|
|
COPY package*.json ./
|
|
RUN npm ci
|
|
COPY . .
|
|
|
|
# El login mágico y el "Ver como…" del panel viven detrás de la constante de build
|
|
# `DEMO` (`import.meta.env.DEV || import.meta.env.VITE_DEMO_UI === "1"`, ver
|
|
# src/pages/LoginPage.tsx, src/components/AppShell.tsx y src/components/DemoSwitcher.tsx).
|
|
# En un build de producción `DEV` es false, así que sin esta variable Vite elimina esas
|
|
# ramas por dead-code elimination: el despliegue quedaba con la landing prometiendo
|
|
# "no pide registro" y un /login sin ninguna cuenta de prueba que ofrecer.
|
|
#
|
|
# Este despliegue ES la demostración del producto, de ahí el default en 1. Cuando deje
|
|
# de serlo, basta pasar `--build-arg VITE_DEMO_UI=0` (o declararlo como build variable en
|
|
# Coolify) y las cuentas demo desaparecen del bundle sin tocar código.
|
|
ARG VITE_DEMO_UI=1
|
|
ENV VITE_DEMO_UI=$VITE_DEMO_UI
|
|
|
|
RUN npm run build
|
|
|
|
# ---- Runtime ----
|
|
FROM node:22-slim
|
|
WORKDIR /app
|
|
ENV NODE_ENV=production
|
|
ENV HOST=0.0.0.0
|
|
ENV PORT=3000
|
|
# La zona del contenedor se fija explícitamente a UTC, que es como se almacenan los
|
|
# instantes en la base. La lógica de agenda ya no depende de ella (usa
|
|
# `businesses.timezone` vía server/lib/time.ts), y dejarla en UTC hace que cualquier
|
|
# recaída a la tz del proceso se note de inmediato en vez de esconderse en dev.
|
|
ENV TZ=UTC
|
|
|
|
COPY package*.json ./
|
|
RUN npm ci --omit=dev && npm cache clean --force
|
|
|
|
# Built frontend (vite outputs to dist/)
|
|
COPY --from=web-build /app/dist ./dist
|
|
|
|
# Server source (tsx runs TS directly in production)
|
|
COPY server ./server
|
|
COPY shared ./shared
|
|
COPY tsconfig.json ./
|
|
|
|
# Persistent SQLite data.
|
|
#
|
|
# NO declares `VOLUME /app/data` aquí. Esa instrucción hace que Docker fabrique un
|
|
# volumen ANÓNIMO en cada arranque, y Coolify los purga al recrear el contenedor:
|
|
# cada despliegue estrenaba base vacía y `ensureSeed()` la resembraba, así que se
|
|
# perdían las citas, los clientes y todo lo configurado en Ajustes. Se verificó
|
|
# comparando el nombre del volumen entre despliegues — cambiaba cada vez.
|
|
#
|
|
# La persistencia la aporta el almacenamiento con nombre declarado en Coolify
|
|
# (`s30f7egdlkx4wyjp59o1iunc-agendamax-data` montado en /app/data), que sobrevive a
|
|
# la recreación del contenedor. Si algún día se despliega en otro sitio, hay que
|
|
# declarar allí un volumen equivalente: sin él la base es efímera.
|
|
RUN mkdir -p /app/data
|
|
|
|
EXPOSE 3000
|
|
CMD ["npx", "tsx", "server/index.ts"]
|