From 57100d3a08986bef8fceb894367938e6aa204bc1 Mon Sep 17 00:00:00 2001 From: nickpons666 Date: Thu, 23 Apr 2026 00:36:32 -0600 Subject: [PATCH] fix(docker): mejorar generacion de .env y APP_KEY en entrypoint - Se corrigen permisos del .env para el usuario laravel (664). - Se mejora la robustez de key:generate usando su -s /bin/bash -c como usuario laravel. - Se asegura que APP_KEY se capture y guarde correctamente usando @ como delimitador en sed. - Limpieza general del entrypoint y mejora de logs. --- .dockerignore | 7 ++ .env.example | 44 +++++---- Dockerfile | 6 ++ docker-compose.prod.yml | 4 +- docker/entrypoint.sh | 200 +++++++++------------------------------- 5 files changed, 87 insertions(+), 174 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..c027ea9 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.env +.env.* +!*.env.example +node_modules/ +.DS_Store +Thumbs.db +*.log \ No newline at end of file diff --git a/.env.example b/.env.example index 680ca28..60be1a3 100755 --- a/.env.example +++ b/.env.example @@ -1,34 +1,44 @@ -# Application - GENERAR CON: php artisan key:generate APP_NAME="Nomina Ventas" -APP_ENV=local +APP_ENV=production APP_KEY= APP_DEBUG=true -APP_URL=http://localhost:80 +APP_URL=https://nomina-pegaso.duckdns.org + +APP_LOCALE=es +APP_FALLBACK_LOCALE=es +APP_FAKER_LOCALE=es_MX + +APP_MAINTENANCE_DRIVER=file + +BCRYPT_ROUNDS=12 LOG_CHANNEL=stack +LOG_STACK=single +LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug -# Database - Docker (OBLIGATORIOS - sin valores por defecto) DB_CONNECTION=mysql -DB_HOST=db -DB_PORT=3306 -DB_DATABASE=nomina_ventas -DB_USERNAME= +DB_HOST=10.10.4.17 +DB_PORT=3390 +DB_DATABASE=nomina_pegaso +DB_USERNAME=nickpons666 DB_PASSWORD= -# MySQL Root (OBLIGATORIO) -MYSQL_ROOT_PASSWORD= - -# Session & Cache SESSION_DRIVER=database SESSION_LIFETIME=120 +SESSION_ENCRYPT=true +SESSION_PATH=/ +SESSION_DOMAIN= + +BROADCAST_CONNECTION=log +FILESYSTEM_DISK=local +QUEUE_CONNECTION=database + CACHE_STORE=database -# Telegram Bot ( OPCIONAL ) +VITE_APP_NAME="${APP_NAME}" + TELEGRAM_BOT_TOKEN= TELEGRAM_WEBHOOK_URL= -# Docker Build -APP_PORT=80 -PUID=1000 -PGID=1000 \ No newline at end of file +RUN_MIGRATIONS=false \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 3f64624..6e31aeb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -85,6 +85,12 @@ RUN chown -R laravel:laravel /var/www/html/storage \ COPY --chown=root:root docker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh +# Create PHP-FPM wrapper to clean empty environment variables +RUN echo '#!/bin/bash' > /usr/local/bin/php-fpm-wrapper && \ + echo 'unset APP_KEY APP_URL APP_ENV APP_DEBUG TELEGRAM_WEBHOOK_URL SESSION_DOMAIN' >> /usr/local/bin/php-fpm-wrapper && \ + echo 'exec /usr/local/sbin/php-fpm "$@"' >> /usr/local/bin/php-fpm-wrapper && \ + chmod +x /usr/local/bin/php-fpm-wrapper + # Expose port 80 (interno) EXPOSE 80 diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 09fa2cb..8325672 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -8,10 +8,10 @@ services: - /media/DATOS/AppData/nomina_pegaso/storage:/var/www/html/storage - /media/DATOS/AppData/nomina_pegaso/bootstrap/cache:/var/www/html/bootstrap/cache environment: - - APP_NAME=Nomina Ventas + - APP_NAME=Nomina Pegasso + - APP_KEY=base64:eo+TyExgS+AS2UszUpV/7qKCvScNTuh0AW1TO/n0ZoU= - APP_ENV=production - APP_DEBUG=true - - APP_KEY= - APP_URL=https://nomina-pegaso.duckdns.org - APP_LOCALE=es - APP_FALLBACK_LOCALE=es diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 6c2e08c..d062fb0 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -8,10 +8,13 @@ echo "========================================" if [ ! -f /var/www/html/artisan ]; then echo "ERROR: No se encontró el código en /var/www/html" - echo "Montando volumen con el código..." exit 1 fi +echo "========================================" +echo " Preparando directorios..." +echo "========================================" + mkdir -p /var/www/html/storage/framework/{cache,sessions,views} mkdir -p /var/www/html/storage/logs mkdir -p /var/www/html/bootstrap/cache @@ -21,149 +24,23 @@ chown -R laravel:laravel /var/www/html/bootstrap/cache chmod -R 775 /var/www/html/storage chmod -R 775 /var/www/html/bootstrap/cache -echo "========================================" -echo " Limpiando cache (antes de sincronizar)..." -echo "========================================" -php /var/www/html/artisan view:clear 2>/dev/null || true -php /var/www/html/artisan config:clear 2>/dev/null || true -php /var/www/html/artisan cache:clear 2>/dev/null || true -php /var/www/html/artisan route:clear 2>/dev/null || true -php /var/www/html/artisan clear:compiled 2>/dev/null || true +# NO cambiar permisos de /var/www/html completo - rompe vendor/ echo "========================================" -echo " Sincronizando variables de entorno..." +echo " Generando archivo .env desde variables de Docker..." echo "========================================" -echo "APP_NAME=${APP_NAME:-}" -echo "APP_ENV=${APP_ENV:-}" -echo "APP_DEBUG=${APP_DEBUG:-}" -echo "APP_URL=${APP_URL:-}" -echo "DB_HOST=${DB_HOST:-}" -echo "DB_PORT=${DB_PORT:-}" -echo "DB_DATABASE=${DB_DATABASE:-}" -echo "DB_USERNAME=${DB_USERNAME:-}" -echo "DB_PASSWORD=${DB_PASSWORD:-}" -echo "APP_KEY=${APP_KEY:-}" - -# Determinar archivo .env a usar +TEMP_ENV="/tmp/.env.docker" ENV_FILE="/var/www/html/.env" -TEMP_ENV="/tmp/.env.build" -# Verificar si ya existe un .env con valores válidos -if [ -f "$ENV_FILE" ]; then - echo ">>> Detectado archivo .env existente" - - # Si hay variables de Docker con valores, actualizar el .env existente - if [ -n "$APP_NAME" ]; then - echo ">>> Actualizando APP_NAME..." - sed -i "s|^APP_NAME=.*|APP_NAME=\"$APP_NAME\"|" "$ENV_FILE" - fi - - if [ -n "$APP_ENV" ]; then - sed -i "s|^APP_ENV=.*|APP_ENV=$APP_ENV|" "$ENV_FILE" - fi - - if [ -n "$APP_DEBUG" ]; then - sed -i "s|^APP_DEBUG=.*|APP_DEBUG=$APP_DEBUG|" "$ENV_FILE" - fi - - if [ -n "$APP_URL" ]; then - sed -i "s|^APP_URL=.*|APP_URL=$APP_URL|" "$ENV_FILE" - fi - - if [ -n "$APP_KEY" ]; then - sed -i "s|^APP_KEY=.*|APP_KEY=$APP_KEY|" "$ENV_FILE" - fi - - if [ -n "$DB_HOST" ]; then - sed -i "s|^DB_HOST=.*|DB_HOST=$DB_HOST|" "$ENV_FILE" - fi - - if [ -n "$DB_PORT" ]; then - sed -i "s|^DB_PORT=.*|DB_PORT=$DB_PORT|" "$ENV_FILE" - fi - - if [ -n "$DB_DATABASE" ]; then - sed -i "s|^DB_DATABASE=.*|DB_DATABASE=$DB_DATABASE|" "$ENV_FILE" - fi - - if [ -n "$DB_USERNAME" ]; then - sed -i "s|^DB_USERNAME=.*|DB_USERNAME=$DB_USERNAME|" "$ENV_FILE" - fi - - if [ -n "$DB_PASSWORD" ]; then - sed -i "s|^DB_PASSWORD=.*|DB_PASSWORD='$DB_PASSWORD'|" "$ENV_FILE" - fi - - if [ -n "$APP_LOCALE" ]; then - sed -i "s|^APP_LOCALE=.*|APP_LOCALE=$APP_LOCALE|" "$ENV_FILE" - fi - - if [ -n "$APP_FALLBACK_LOCALE" ]; then - sed -i "s|^APP_FALLBACK_LOCALE=.*|APP_FALLBACK_LOCALE=$APP_FALLBACK_LOCALE|" "$ENV_FILE" - fi - - if [ -n "$SESSION_DRIVER" ]; then - sed -i "s|^SESSION_DRIVER=.*|SESSION_DRIVER=$SESSION_DRIVER|" "$ENV_FILE" - fi - - if [ -n "$SESSION_LIFETIME" ]; then - sed -i "s|^SESSION_LIFETIME=.*|SESSION_LIFETIME=$SESSION_LIFETIME|" "$ENV_FILE" - fi - - if [ -n "$SESSION_ENCRYPT" ]; then - sed -i "s|^SESSION_ENCRYPT=.*|SESSION_ENCRYPT=$SESSION_ENCRYPT|" "$ENV_FILE" - fi - - if [ -n "$BCRYPT_ROUNDS" ]; then - sed -i "s|^BCRYPT_ROUNDS=.*|BCRYPT_ROUNDS=$BCRYPT_ROUNDS|" "$ENV_FILE" - fi - - if [ -n "$LOG_CHANNEL" ]; then - sed -i "s|^LOG_CHANNEL=.*|LOG_CHANNEL=$LOG_CHANNEL|" "$ENV_FILE" - fi - - if [ -n "$LOG_LEVEL" ]; then - sed -i "s|^LOG_LEVEL=.*|LOG_LEVEL=$LOG_LEVEL|" "$ENV_FILE" - fi - - if [ -n "$TELEGRAM_BOT_TOKEN" ]; then - sed -i "s|^TELEGRAM_BOT_TOKEN=.*|TELEGRAM_BOT_TOKEN=$TELEGRAM_BOT_TOKEN|" "$ENV_FILE" - fi - - if [ -n "$TELEGRAM_WEBHOOK_URL" ]; then - sed -i "s|^TELEGRAM_WEBHOOK_URL=.*|TELEGRAM_WEBHOOK_URL=$TELEGRAM_WEBHOOK_URL|" "$ENV_FILE" - fi - - # Verificar si APP_KEY necesita generarse - CURRENT_KEY=$(grep "^APP_KEY=" "$ENV_FILE" | cut -d'=' -f2-) - if [ -z "$CURRENT_KEY" ] || [ "$CURRENT_KEY" == "base64:" ]; then - echo ">>> Generando APP_KEY..." - NEW_KEY=$(php /var/www/html/artisan key:generate --show --no-ansi 2>/dev/null || true) - if [ -n "$NEW_KEY" ]; then - sed -i "s|^APP_KEY=.*|APP_KEY=$NEW_KEY|" "$ENV_FILE" - export APP_KEY=$NEW_KEY - fi - fi - - chown laravel:laravel "$ENV_FILE" - chmod 640 "$ENV_FILE" - - echo ">>> Archivo .env actualizado con variables de Docker" -else - echo ">>> No existe .env, generando uno nuevo..." - - # Generar APP_KEY si no existe - if [ -z "$APP_KEY" ]; then - echo ">>> Generando APP_KEY..." - NEW_KEY=$(php /var/www/html/artisan key:generate --show --no-ansi 2>/dev/null || true) - APP_KEY=$NEW_KEY - fi - - cat > "$TEMP_ENV" << ENVEOF +# Eliminar .env existente si existe +rm -f "$ENV_FILE" 2>/dev/null || true + +# Construir el archivo .env (Incluimos APP_KEY si ya viene en el entorno) +cat > "$TEMP_ENV" << ENVEOF APP_NAME="${APP_NAME:-Nomina Ventas}" APP_ENV="${APP_ENV:-production}" -APP_KEY=${APP_KEY} +APP_KEY="${APP_KEY}" APP_DEBUG="${APP_DEBUG:-false}" APP_URL="${APP_URL:-http://localhost}" APP_LOCALE="${APP_LOCALE:-es}" @@ -180,12 +57,12 @@ DB_HOST="${DB_HOST:-127.0.0.1}" DB_PORT="${DB_PORT:-3306}" DB_DATABASE="${DB_DATABASE:-laravel}" DB_USERNAME="${DB_USERNAME:-root}" -DB_PASSWORD='${DB_PASSWORD}' +DB_PASSWORD="${DB_PASSWORD}" SESSION_DRIVER="${SESSION_DRIVER:-database}" SESSION_LIFETIME="${SESSION_LIFETIME:-120}" SESSION_ENCRYPT="${SESSION_ENCRYPT:-true}" -SESSION_PATH="/" -SESSION_DOMAIN=null +SESSION_PATH="${SESSION_PATH:-/}" +SESSION_DOMAIN="${SESSION_DOMAIN}" BROADCAST_CONNECTION="${BROADCAST_CONNECTION:-log}" FILESYSTEM_DISK="${FILESYSTEM_DISK:-local}" QUEUE_CONNECTION="${QUEUE_CONNECTION:-database}" @@ -193,23 +70,42 @@ CACHE_STORE="${CACHE_STORE:-database}" VITE_APP_NAME="\${APP_NAME}" TELEGRAM_BOT_TOKEN="${TELEGRAM_BOT_TOKEN}" TELEGRAM_WEBHOOK_URL="${TELEGRAM_WEBHOOK_URL}" +RUN_MIGRATIONS="${RUN_MIGRATIONS:-false}" ENVEOF - if [ -f "$TEMP_ENV" ]; then - mv "$TEMP_ENV" "$ENV_FILE" - chown laravel:laravel "$ENV_FILE" - chmod 640 "$ENV_FILE" - echo ">>> Archivo .env creado" +# Copiar al destino y asegurar que el usuario laravel pueda leerlo +cp "$TEMP_ENV" "$ENV_FILE" +chown laravel:laravel "$ENV_FILE" +chmod 664 "$ENV_FILE" + +echo ">>> .env generado" + +echo "========================================" +echo " Verificando APP_KEY..." +echo "========================================" + +APP_KEY_VALUE=$(grep "^APP_KEY=" "$ENV_FILE" | cut -d'=' -f2- | tr -d '"') +if [ -z "$APP_KEY_VALUE" ]; then + echo ">>> Generando APP_KEY..." + # Ejecutar como usuario laravel para evitar problemas de permisos + NEW_KEY=$(su -s /bin/bash -c "php /var/www/html/artisan key:generate --show --no-ansi" laravel) + + if [ -n "$NEW_KEY" ]; then + # Usar @ como delimitador en sed por si la llave contiene slashes + sed -i "s@^APP_KEY=.*@APP_KEY=$NEW_KEY@" "$ENV_FILE" + echo ">>> APP_KEY generado y guardado." + else + echo ">>> ERROR: No se pudo generar APP_KEY" fi +else + echo ">>> APP_KEY detectada en el entorno/archivo." fi -# Verificar contenido del .env echo "" -echo ">>> Contenido actual de .env:" -grep -E "^(APP_NAME|APP_ENV|APP_DEBUG|APP_URL|DB_HOST|DB_PORT|DB_DATABASE|APP_KEY)=" "$ENV_FILE" 2>/dev/null || echo "No se pudo leer el .env" +echo ">>> Contenido del .env (primeras líneas):" +head -8 "$ENV_FILE" echo "" -# Limpiar cache (importante despues de sincronizar) echo "========================================" echo " Limpiando cache..." echo "========================================" @@ -219,12 +115,6 @@ php /var/www/html/artisan cache:clear 2>/dev/null || true php /var/www/html/artisan route:clear 2>/dev/null || true php /var/www/html/artisan clear:compiled 2>/dev/null || true -# NO hacer config:cache cuando el .env se sincroniza desde Docker -# Esto causa que PHP-FPM use valores en cache que no existen todavia -# En produccion con volumenes montados, Laravel lee el .env directamente -echo ">> Cache omitido - usando .env directo" -# php /var/www/html/artisan config:cache 2>&1 || true - echo "========================================" echo " Estado de la aplicación" echo "========================================" @@ -235,5 +125,5 @@ echo "========================================" echo " Iniciando servicios..." echo "========================================" -php-fpm & +php-fpm-wrapper & nginx -g "daemon off;" \ No newline at end of file