From bbcd85eff7d53e2d765b58efd00674974a61f4b3 Mon Sep 17 00:00:00 2001 From: Marco Gallegos Date: Mon, 25 Aug 2025 18:40:44 -0600 Subject: [PATCH] feat: Release version 1.3.1 with Docker optimization and comprehensive documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update version to 1.3.1 in package.json and docker-compose.yml - Optimize Dockerfile with proper data directory structure for production - Add comprehensive Docker documentation (DOCKER.md) - Include deployment and backup scripts (deploy.sh, backup.sh) - Add .env.example for environment configuration - Improve README with detailed deployment instructions - Fix database path handling for Docker production environment - Add health checks and proper Docker Compose configuration - Remove development task documentation - Update .gitignore to exclude backup directories 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .env.example | 8 ++++ .gitignore | 1 + DOCKER.md | 92 ++++++++++++++++++++++++++++++++++++++++++++++ Dockerfile | 7 ++-- README.md | 33 +++++++++++++---- backup.sh | 53 ++++++++++++++++++++++++++ deploy.sh | 59 +++++++++++++++++++++++++++++ docker-compose.yml | 10 ++++- package.json | 2 +- server.js | 12 ++++-- 10 files changed, 261 insertions(+), 16 deletions(-) create mode 100644 .env.example create mode 100644 DOCKER.md create mode 100755 backup.sh create mode 100755 deploy.sh diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..1d3c8a0 --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +# Variables de entorno para AP-POS +# Copiar este archivo como .env y configurar los valores + +# Clave secreta para las sesiones (CAMBIAR en producción) +SESSION_SECRET=tu-clave-secreta-muy-segura-cambiala-en-produccion + +# Entorno de ejecución +NODE_ENV=production \ No newline at end of file diff --git a/.gitignore b/.gitignore index 64b7d7a..c6acf62 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ # Local Database ap-pos.db +backups/ # Docmuentation tasks dev-tasks.md diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 0000000..f19e5ae --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,92 @@ +# Guía de Docker para AP-POS + +## Configuración inicial + +1. **Configurar variables de entorno**: + ```bash + cp .env.example .env + # Editar .env con tus valores específicos + ``` + +2. **Construir y levantar los servicios**: + ```bash + docker-compose up -d --build + ``` + +3. **Verificar que esté funcionando**: + ```bash + docker-compose ps + docker-compose logs ap-pos + ``` + +4. **Acceder a la aplicación**: + - URL: http://localhost:3111 + - Primera vez: será redirigido a `/setup.html` para crear el usuario admin + +## Comandos útiles + +### Ver logs en tiempo real +```bash +docker-compose logs -f ap-pos +``` + +### Reiniciar el servicio +```bash +docker-compose restart ap-pos +``` + +### Detener y eliminar todo +```bash +docker-compose down +``` + +### Backup de la base de datos +```bash +# Crear backup +docker-compose exec ap-pos cp /app/data/ap-pos.db /app/data/backup-$(date +%Y%m%d_%H%M%S).db + +# O desde el host +docker cp ap-pos:/app/data/ap-pos.db ./backup-ap-pos.db +``` + +### Restaurar base de datos +```bash +# Detener el servicio +docker-compose stop ap-pos + +# Restaurar desde backup +docker cp ./backup-ap-pos.db ap-pos:/app/data/ap-pos.db + +# Reiniciar +docker-compose start ap-pos +``` + +## Persistencia de datos + +- La base de datos SQLite se almacena en el volumen Docker `ap_pos_data` +- Los datos persisten entre reinicios del contenedor +- El volumen se mantiene incluso si el contenedor se elimina + +## Troubleshooting + +### El contenedor no inicia +```bash +# Ver logs detallados +docker-compose logs ap-pos + +# Verificar el health check +docker-compose ps +``` + +### Problemas de permisos +```bash +# Verificar permisos del volumen +docker-compose exec ap-pos ls -la /app/data/ +``` + +### Reset completo +```bash +# CUIDADO: Esto elimina todos los datos +docker-compose down -v +docker-compose up -d --build +``` \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 75d0b8b..bef4f4c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,9 +16,10 @@ RUN npm ci --omit=dev && npm cache clean --force # 6. Copiar el resto de la aplicación COPY . . -# 7. Crear usuario no root y darle permisos -RUN addgroup -S app && adduser -S app -G app \ - && chown -R app:app /app +# 7. Crear directorio para la base de datos y usuario no root +RUN mkdir -p /app/data && \ + addgroup -S app && adduser -S app -G app && \ + chown -R app:app /app USER app # 8. Exponer el puerto diff --git a/README.md b/README.md index 1bddc3f..52bfe82 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,31 @@ El sistema está diseñado para ser desplegado fácilmente utilizando Docker y D ### Pasos para el despliegue -1. Clona o descarga este repositorio en tu máquina local. -2. Abre una terminal y navega hasta el directorio raíz del proyecto. -3. Ejecuta el siguiente comando para construir y levantar el contenedor de la aplicación en segundo plano: +1. **Clona o descarga** este repositorio en tu máquina local. - ```bash - docker-compose up -d --build - ``` +2. **Configura las variables de entorno**: + ```bash + cp .env.example .env + # Edita el archivo .env con una clave secreta segura + ``` -4. Una vez que el comando termine, la aplicación estará disponible en tu navegador en la dirección `http://localhost:3000`. +3. **Construye y levanta** el contenedor: + ```bash + docker-compose up -d --build + ``` -La base de datos y toda la información se almacenarán localmente dentro de los volúmenes de Docker gestionados por `docker-compose`. +4. **Verifica que esté funcionando**: + ```bash + docker-compose ps + docker-compose logs ap-pos + ``` + +5. **Accede a la aplicación**: + - URL: `http://localhost:3111` + - En la primera ejecución serás redirigido a `/setup.html` para crear el usuario administrador + +### Persistencia de datos + +- La base de datos SQLite se almacena en un volumen Docker persistente +- Los datos se mantienen entre reinicios y actualizaciones del contenedor +- Para más información sobre Docker, consulta [DOCKER.md](./DOCKER.md) diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..e59e9d9 --- /dev/null +++ b/backup.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# Script de backup para AP-POS +# Crea backup de la base de datos SQLite + +set -e + +BACKUP_DIR="./backups" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +BACKUP_FILE="backup-ap-pos-${TIMESTAMP}.db" + +echo "💾 Creando backup de la base de datos AP-POS..." + +# Crear directorio de backups si no existe +mkdir -p "$BACKUP_DIR" + +# Verificar que el contenedor esté corriendo +if ! docker compose ps ap-pos | grep -q "running"; then + echo "❌ Error: El contenedor ap-pos no está corriendo" + echo " Ejecuta: docker compose up -d" + exit 1 +fi + +# Crear backup desde el contenedor +echo "📋 Copiando base de datos..." +docker compose exec -T ap-pos cp /app/data/ap-pos.db /tmp/backup.db + +# Copiar al host +docker compose cp ap-pos:/tmp/backup.db "${BACKUP_DIR}/${BACKUP_FILE}" + +# Limpiar archivo temporal +docker compose exec -T ap-pos rm /tmp/backup.db + +# Verificar que el backup se creó correctamente +if [ -f "${BACKUP_DIR}/${BACKUP_FILE}" ]; then + BACKUP_SIZE=$(ls -lh "${BACKUP_DIR}/${BACKUP_FILE}" | awk '{print $5}') + echo "✅ Backup creado exitosamente:" + echo " 📁 Archivo: ${BACKUP_DIR}/${BACKUP_FILE}" + echo " 📊 Tamaño: ${BACKUP_SIZE}" + + # Mostrar backups disponibles + echo "" + echo "📂 Backups disponibles:" + ls -lht "${BACKUP_DIR}"/ | head -10 +else + echo "❌ Error: No se pudo crear el backup" + exit 1 +fi + +# Opcional: Limpiar backups antiguos (mantener solo los últimos 10) +echo "🧹 Limpiando backups antiguos (manteniendo los últimos 10)..." +ls -t "${BACKUP_DIR}"/backup-ap-pos-*.db 2>/dev/null | tail -n +11 | xargs -r rm +echo "✅ Limpieza completada" \ No newline at end of file diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..c9e7f1d --- /dev/null +++ b/deploy.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# Script de despliegue para AP-POS +# Autor: Sistema AP-POS + +set -e # Exit on any error + +echo "🚀 Desplegando AP-POS con Docker..." + +# Verificar que Docker esté instalado +if ! command -v docker &> /dev/null; then + echo "❌ Error: Docker no está instalado" + echo " Instalar desde: https://docs.docker.com/get-docker/" + exit 1 +fi + +# Verificar que Docker Compose esté disponible +if ! docker compose version &> /dev/null; then + echo "❌ Error: Docker Compose no está disponible" + echo " Instalar desde: https://docs.docker.com/compose/install/" + exit 1 +fi + +# Crear archivo .env si no existe +if [ ! -f .env ]; then + echo "📝 Creando archivo .env desde template..." + cp .env.example .env + echo "⚠️ IMPORTANTE: Edita el archivo .env con una clave secreta segura antes de usar en producción" +fi + +# Detener contenedores existentes si están corriendo +echo "🔄 Deteniendo contenedores existentes..." +docker compose down 2>/dev/null || true + +# Construir y levantar los servicios +echo "🏗️ Construyendo y levantando servicios..." +docker compose up -d --build + +# Esperar un poco para que el servicio inicie +echo "⏳ Esperando que el servicio inicie..." +sleep 10 + +# Verificar el estado +echo "🔍 Verificando estado del servicio..." +docker compose ps + +# Mostrar logs recientes +echo "📋 Logs recientes:" +docker compose logs --tail=20 ap-pos + +# Verificar que el servicio responde +echo "🏥 Verificando conectividad..." +if curl -s -o /dev/null -w "%{http_code}" http://localhost:3111/login.html | grep -q "200"; then + echo "✅ ¡Despliegue exitoso!" + echo "🌐 Aplicación disponible en: http://localhost:3111" + echo "📖 Para más información, consulta DOCKER.md" +else + echo "⚠️ El servicio está iniciando. Verifica con: docker compose logs ap-pos" +fi \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 25063d5..4481409 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,14 +1,22 @@ services: ap-pos: - image: marcogll/ap_pos:1.3-latest + image: marcogll/ap_pos:1.3.1 container_name: ap-pos restart: unless-stopped ports: - "3111:3111" environment: NODE_ENV: production + SESSION_SECRET: ${SESSION_SECRET:-your-very-secret-key-change-it-in-production} volumes: - ap_pos_data:/app/data + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3111/login.html"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s volumes: ap_pos_data: + driver: local diff --git a/package.json b/package.json index 40ae357..a0f6495 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ap-pos", - "version": "1.0.0", + "version": "1.3.1", "main": "app.js", "scripts": { "start": "node server.js" diff --git a/server.js b/server.js index 91e34d7..0823e82 100644 --- a/server.js +++ b/server.js @@ -25,8 +25,10 @@ app.use(session({ })); // --- DATABASE INITIALIZATION --- -// Usar un path absoluto para asegurar que la DB siempre se cree en la carpeta del proyecto. -const dbPath = path.join(__dirname, 'ap-pos.db'); +// Usar un path que funcione tanto en desarrollo como en Docker +const dbPath = process.env.NODE_ENV === 'production' + ? path.join(__dirname, 'data', 'ap-pos.db') + : path.join(__dirname, 'ap-pos.db'); console.log(`Connecting to database at: ${dbPath}`); const db = new sqlite3.Database(dbPath, (err) => { @@ -144,7 +146,11 @@ function startServer() { // Middleware para manejar la redirección a la página de configuración const checkSetup = (req, res, next) => { - const allowedPaths = ['/setup.html', '/setup.js', '/api/setup', '/styles.css', '/src/logo.png', '/api/check-auth']; + const allowedPaths = [ + '/setup.html', '/setup.js', '/api/setup', + '/login.html', '/login.js', '/api/login', + '/styles.css', '/src/logo.png', '/api/check-auth' + ]; if (needsSetup && !allowedPaths.includes(req.path)) { return res.redirect('/setup.html'); }