Harden Docker deploy for legacy environments
This commit is contained in:
parent
b37171a438
commit
1c6611addb
93
Dockerfile
93
Dockerfile
|
|
@ -1,44 +1,81 @@
|
||||||
FROM php:8.2-fpm
|
FROM php:8.3-cli AS vendor
|
||||||
|
|
||||||
# Installa dipendenze di sistema
|
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
git \
|
git \
|
||||||
curl \
|
libfreetype6-dev \
|
||||||
|
libicu-dev \
|
||||||
|
libjpeg62-turbo-dev \
|
||||||
libpng-dev \
|
libpng-dev \
|
||||||
libonig-dev \
|
libzip-dev \
|
||||||
libxml2-dev \
|
|
||||||
zip \
|
|
||||||
unzip \
|
unzip \
|
||||||
nodejs \
|
zip \
|
||||||
npm
|
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
|
||||||
|
&& docker-php-ext-install -j"$(nproc)" gd intl zip \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Pulisce cache
|
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Installa estensioni PHP
|
WORKDIR /app
|
||||||
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
|
COPY composer.json composer.lock ./
|
||||||
|
RUN composer install \
|
||||||
|
--no-dev \
|
||||||
|
--prefer-dist \
|
||||||
|
--no-interaction \
|
||||||
|
--no-progress \
|
||||||
|
--no-scripts \
|
||||||
|
--optimize-autoloader
|
||||||
|
|
||||||
# Installa Composer
|
FROM node:20-bookworm-slim AS frontend
|
||||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package.json package-lock.json* ./
|
||||||
|
RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi
|
||||||
|
COPY --from=vendor /app/vendor ./vendor
|
||||||
|
COPY resources ./resources
|
||||||
|
COPY public ./public
|
||||||
|
COPY vite.config.js package.json postcss.config.js tailwind.config.js ./
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM php:8.3-fpm AS runtime
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
curl \
|
||||||
|
default-mysql-client \
|
||||||
|
git \
|
||||||
|
libfreetype6-dev \
|
||||||
|
libicu-dev \
|
||||||
|
libjpeg62-turbo-dev \
|
||||||
|
libonig-dev \
|
||||||
|
libpng-dev \
|
||||||
|
libxml2-dev \
|
||||||
|
libzip-dev \
|
||||||
|
unzip \
|
||||||
|
zip \
|
||||||
|
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
|
||||||
|
&& docker-php-ext-install -j"$(nproc)" bcmath exif gd intl mbstring opcache pcntl pdo_mysql zip \
|
||||||
|
&& pecl install redis \
|
||||||
|
&& docker-php-ext-enable redis \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
# Imposta directory di lavoro
|
|
||||||
WORKDIR /var/www
|
WORKDIR /var/www
|
||||||
|
|
||||||
# Copia file applicazione
|
COPY --chown=www-data:www-data . .
|
||||||
COPY . /var/www
|
COPY --chown=www-data:www-data --from=vendor /app/vendor ./vendor
|
||||||
|
COPY --chown=www-data:www-data --from=frontend /app/public/build ./public/build
|
||||||
|
COPY --chown=www-data:www-data docker/entrypoint.sh /entrypoint.sh
|
||||||
|
COPY --chown=www-data:www-data docker/php/local.ini /usr/local/etc/php/conf.d/99-netgescon.ini
|
||||||
|
|
||||||
# Installa dipendenze PHP
|
RUN chmod +x /entrypoint.sh \
|
||||||
RUN composer install --optimize-autoloader --no-dev
|
&& mkdir -p storage/framework/cache/data storage/framework/sessions storage/framework/views bootstrap/cache /opt/netgescon \
|
||||||
|
&& cp -a public /opt/netgescon/public \
|
||||||
|
&& composer dump-autoload --no-dev --optimize \
|
||||||
|
&& chmod -R 775 storage bootstrap/cache
|
||||||
|
|
||||||
# Installa dipendenze Node.js
|
|
||||||
RUN npm install && npm run build
|
|
||||||
|
|
||||||
# Imposta permessi
|
|
||||||
RUN chown -R www-data:www-data /var/www \
|
|
||||||
&& chmod -R 755 /var/www/storage \
|
|
||||||
&& chmod -R 755 /var/www/bootstrap/cache
|
|
||||||
|
|
||||||
# Espone porta 9000
|
|
||||||
EXPOSE 9000
|
EXPOSE 9000
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
CMD ["php-fpm"]
|
CMD ["php-fpm"]
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
|
@ -29,14 +30,14 @@ public function store(LoginRequest $request): RedirectResponse
|
||||||
|
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
|
|
||||||
if ($user && ! $user->is_active) {
|
if ($user && $this->userTableHasColumn($user, 'is_active') && ! $user->is_active) {
|
||||||
Auth::guard('web')->logout();
|
Auth::guard('web')->logout();
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'email' => 'Account disattivato. Contatta il super-admin.',
|
'email' => 'Account disattivato. Contatta il super-admin.',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($user && $user->registration_status !== 'approved') {
|
if ($user && $this->userTableHasColumn($user, 'registration_status') && $user->registration_status !== 'approved') {
|
||||||
Auth::guard('web')->logout();
|
Auth::guard('web')->logout();
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'email' => 'Registrazione in attesa di approvazione del super-admin.',
|
'email' => 'Registrazione in attesa di approvazione del super-admin.',
|
||||||
|
|
@ -44,7 +45,7 @@ public function store(LoginRequest $request): RedirectResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
$requireEmailVerification = SystemSetting::bool('require_email_verification', true);
|
$requireEmailVerification = SystemSetting::bool('require_email_verification', true);
|
||||||
$isSelfRegistered = $user && ! empty($user->requested_role);
|
$isSelfRegistered = $user && $this->userTableHasColumn($user, 'requested_role') && ! empty($user->requested_role);
|
||||||
if ($user && $isSelfRegistered && $requireEmailVerification && ! $user->hasVerifiedEmail()) {
|
if ($user && $isSelfRegistered && $requireEmailVerification && ! $user->hasVerifiedEmail()) {
|
||||||
Auth::guard('web')->logout();
|
Auth::guard('web')->logout();
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
|
|
@ -57,6 +58,11 @@ public function store(LoginRequest $request): RedirectResponse
|
||||||
return redirect()->intended(route('dashboard', absolute: false));
|
return redirect()->intended(route('dashboard', absolute: false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function userTableHasColumn($user, string $column): bool
|
||||||
|
{
|
||||||
|
return Schema::connection($user->getConnectionName())->hasColumn($user->getTable(), $column);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy an authenticated session.
|
* Destroy an authenticated session.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
class SystemSetting extends Model
|
class SystemSetting extends Model
|
||||||
{
|
{
|
||||||
|
|
@ -12,7 +13,15 @@ class SystemSetting extends Model
|
||||||
|
|
||||||
public static function getValue(string $key, mixed $default = null): mixed
|
public static function getValue(string $key, mixed $default = null): mixed
|
||||||
{
|
{
|
||||||
$setting = static::query()->where('key', $key)->value('value');
|
if (! static::settingsTableExists()) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$setting = static::query()->where('key', $key)->value('value');
|
||||||
|
} catch (Throwable) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
if ($setting === null) {
|
if ($setting === null) {
|
||||||
return $default;
|
return $default;
|
||||||
|
|
@ -25,6 +34,10 @@ public static function getValue(string $key, mixed $default = null): mixed
|
||||||
|
|
||||||
public static function setValue(string $key, mixed $value): void
|
public static function setValue(string $key, mixed $value): void
|
||||||
{
|
{
|
||||||
|
if (! static::settingsTableExists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$storedValue = is_string($value) ? $value : json_encode($value);
|
$storedValue = is_string($value) ? $value : json_encode($value);
|
||||||
|
|
||||||
static::query()->updateOrCreate(
|
static::query()->updateOrCreate(
|
||||||
|
|
@ -37,4 +50,15 @@ public static function bool(string $key, bool $default = false): bool
|
||||||
{
|
{
|
||||||
return filter_var(static::getValue($key, $default), FILTER_VALIDATE_BOOL);
|
return filter_var(static::getValue($key, $default), FILTER_VALIDATE_BOOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static function settingsTableExists(): bool
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$model = new static();
|
||||||
|
|
||||||
|
return $model->getConnection()->getSchemaBuilder()->hasTable($model->getTable());
|
||||||
|
} catch (Throwable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
use App\Models\Soggetto;
|
use App\Models\Soggetto;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Services\Anagrafiche\RubricaPhoneLookupService;
|
use App\Services\Anagrafiche\RubricaPhoneLookupService;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
class LiveIncomingCallService
|
class LiveIncomingCallService
|
||||||
{
|
{
|
||||||
|
|
@ -15,6 +16,10 @@ class LiveIncomingCallService
|
||||||
*/
|
*/
|
||||||
public function getForUser(User $user): ?array
|
public function getForUser(User $user): ?array
|
||||||
{
|
{
|
||||||
|
if (! Schema::hasTable('communication_messages')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
$userExtension = trim((string) ($user->pbx_extension ?? ''));
|
$userExtension = trim((string) ($user->pbx_extension ?? ''));
|
||||||
$watchedExtensions = app(PbxRoutingService::class)->getWatchedExtensionsForUser($user);
|
$watchedExtensions = app(PbxRoutingService::class)->getWatchedExtensionsForUser($user);
|
||||||
$popupRestricted = (bool) ($user->pbx_popup_enabled ?? false) && count($watchedExtensions) > 0;
|
$popupRestricted = (bool) ($user->pbx_popup_enabled ?? false) && count($watchedExtensions) > 0;
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ public function resolveByExtension(?string $extension): array
|
||||||
}
|
}
|
||||||
|
|
||||||
$stabileId = null;
|
$stabileId = null;
|
||||||
if (method_exists($user, 'stabiliAssegnati')) {
|
if ($this->canResolveAssignedStabili() && method_exists($user, 'stabiliAssegnati')) {
|
||||||
$stabileId = $user->stabiliAssegnati()->value('stabili.id');
|
$stabileId = $user->stabiliAssegnati()->value('stabili.id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,7 +119,7 @@ public function resolveByIncomingLine(?string $line): array
|
||||||
if ($mappedUser instanceof User) {
|
if ($mappedUser instanceof User) {
|
||||||
$targetRouting = [
|
$targetRouting = [
|
||||||
'user_id' => (int) $mappedUser->id,
|
'user_id' => (int) $mappedUser->id,
|
||||||
'stabile_id' => method_exists($mappedUser, 'stabiliAssegnati') ? ((int) ($mappedUser->stabiliAssegnati()->value('stabili.id') ?? 0) ?: null): null,
|
'stabile_id' => $this->canResolveAssignedStabili() && method_exists($mappedUser, 'stabiliAssegnati') ? ((int) ($mappedUser->stabiliAssegnati()->value('stabili.id') ?? 0) ?: null): null,
|
||||||
'user' => $mappedUser,
|
'user' => $mappedUser,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
@ -335,13 +335,18 @@ private function resolveAmministratoreForUser(User $user): ?Amministratore
|
||||||
}
|
}
|
||||||
|
|
||||||
$amministratoreId = null;
|
$amministratoreId = null;
|
||||||
if (method_exists($user, 'stabiliAssegnati')) {
|
if ($this->canResolveAssignedStabili() && method_exists($user, 'stabiliAssegnati')) {
|
||||||
$amministratoreId = $user->stabiliAssegnati()->value('stabili.amministratore_id');
|
$amministratoreId = $user->stabiliAssegnati()->value('stabili.amministratore_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $amministratoreId ? Amministratore::query()->find((int) $amministratoreId) : null;
|
return $amministratoreId ? Amministratore::query()->find((int) $amministratoreId) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function canResolveAssignedStabili(): bool
|
||||||
|
{
|
||||||
|
return Schema::hasTable('collaboratore_stabile') && Schema::hasTable('stabili');
|
||||||
|
}
|
||||||
|
|
||||||
private function resolveAmministratoreIdForUser(User $user): ?int
|
private function resolveAmministratoreIdForUser(User $user): ?int
|
||||||
{
|
{
|
||||||
$amministratore = $this->resolveAmministratoreForUser($user);
|
$amministratore = $this->resolveAmministratoreForUser($user);
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,14 @@
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"laravel": {
|
"laravel": {
|
||||||
"dont-discover": []
|
"dont-discover": [
|
||||||
|
"laravel/breeze",
|
||||||
|
"laravel/pail",
|
||||||
|
"laravel/sail",
|
||||||
|
"nunomaduro/collision",
|
||||||
|
"nunomaduro/termwind",
|
||||||
|
"pestphp/pest-plugin-laravel"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,12 @@ set -euo pipefail
|
||||||
|
|
||||||
cd /var/www
|
cd /var/www
|
||||||
|
|
||||||
|
if [[ -d /opt/netgescon/public ]]; then
|
||||||
|
mkdir -p /var/www/public
|
||||||
|
find /var/www/public -mindepth 1 -maxdepth 1 -exec rm -rf {} + 2>/dev/null || true
|
||||||
|
cp -a /opt/netgescon/public/. /var/www/public/
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -n "${MYSQL_SSL_VERIFY_SERVER_CERT:-}" ]]; then
|
if [[ -n "${MYSQL_SSL_VERIFY_SERVER_CERT:-}" ]]; then
|
||||||
cat > /root/.my.cnf <<EOF
|
cat > /root/.my.cnf <<EOF
|
||||||
[client]
|
[client]
|
||||||
|
|
@ -19,6 +25,14 @@ if [[ "${FIX_PERMISSIONS:-false}" == "true" ]]; then
|
||||||
chmod -R 775 /var/www/storage /var/www/bootstrap/cache || true
|
chmod -R 775 /var/www/storage /var/www/bootstrap/cache || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
rm -f \
|
||||||
|
/var/www/bootstrap/cache/packages.php \
|
||||||
|
/var/www/bootstrap/cache/services.php \
|
||||||
|
/var/www/bootstrap/cache/config.php \
|
||||||
|
/var/www/bootstrap/cache/events.php \
|
||||||
|
/var/www/bootstrap/cache/routes-v7.php \
|
||||||
|
/var/www/bootstrap/cache/routes.php
|
||||||
|
|
||||||
if [[ "${WAIT_FOR_DB:-true}" == "true" ]] && [[ -n "${DB_HOST:-}" ]]; then
|
if [[ "${WAIT_FOR_DB:-true}" == "true" ]] && [[ -n "${DB_HOST:-}" ]]; then
|
||||||
for i in {1..30}; do
|
for i in {1..30}; do
|
||||||
if mysqladmin ping -h "${DB_HOST}" -P "${DB_PORT:-3306}" -u "${DB_USERNAME:-root}" -p"${DB_PASSWORD:-}" --silent; then
|
if mysqladmin ping -h "${DB_HOST}" -P "${DB_PORT:-3306}" -u "${DB_USERNAME:-root}" -p"${DB_PASSWORD:-}" --silent; then
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,134 @@
|
||||||
# Docker setup (distribuzione)
|
# Docker setup operativo Day0
|
||||||
|
|
||||||
## Prerequisiti
|
Questo documento descrive lo stack Docker realmente usato nel repository operativo `netgescon-day0`.
|
||||||
- Docker + Docker Compose
|
|
||||||
- Accesso ai volumi legacy (read-only)
|
|
||||||
|
|
||||||
## 1) Configurazione
|
## Obiettivo
|
||||||
1. Copia `.env.docker.example` → `.env`
|
|
||||||
2. Compila le variabili principali:
|
|
||||||
- `APP_URL`
|
|
||||||
- `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD`, `DB_ROOT_PASSWORD`
|
|
||||||
- `LEGACY_ARCHIVES_PATH`
|
|
||||||
|
|
||||||
## 2) Avvio
|
Avviare solo l'applicativo NetGescon in container, lasciando fuori:
|
||||||
```
|
|
||||||
docker compose -f docker/docker-compose.prod.yml up -d
|
- MySQL esistente
|
||||||
|
- archivi gia presenti
|
||||||
|
- storage gia popolato, quando serve lavorare sui dati correnti
|
||||||
|
|
||||||
|
## Stack effettivo
|
||||||
|
|
||||||
|
Il file autorevole e `docker-compose.yml` nella root del repository.
|
||||||
|
|
||||||
|
Servizi inclusi:
|
||||||
|
|
||||||
|
- `app`
|
||||||
|
- `queue`
|
||||||
|
- `scheduler`
|
||||||
|
- `nginx`
|
||||||
|
- `redis`
|
||||||
|
- `mailhog`
|
||||||
|
|
||||||
|
Il wrapper operativo e:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash docker/run-app-stack.sh up -d --build
|
||||||
```
|
```
|
||||||
|
|
||||||
## 3) Aggiornamenti
|
## 1) Configurazione locale
|
||||||
```
|
|
||||||
bash scripts/update-docker.sh
|
Creare il file `.env.docker.local` partendo da `.env.docker.local.example`.
|
||||||
|
|
||||||
|
Variabili minime da verificare:
|
||||||
|
|
||||||
|
- `APP_URL`
|
||||||
|
- `APP_PORT`
|
||||||
|
- `NETGESCON_DB_HOST`
|
||||||
|
- `NETGESCON_DB_PORT`
|
||||||
|
- `NETGESCON_DB_DATABASE`
|
||||||
|
- `NETGESCON_DB_USERNAME`
|
||||||
|
- `NETGESCON_DB_PASSWORD`
|
||||||
|
- `NETGESCON_STORAGE_PATH`
|
||||||
|
- `NETGESCON_CACHE_PATH`
|
||||||
|
- `RUN_MIGRATIONS`
|
||||||
|
|
||||||
|
Valori consigliati per lavorare sui dati esistenti:
|
||||||
|
|
||||||
|
```dotenv
|
||||||
|
RUN_MIGRATIONS=false
|
||||||
|
NETGESCON_STORAGE_PATH=./storage
|
||||||
|
NETGESCON_CACHE_PATH=./bootstrap/cache
|
||||||
```
|
```
|
||||||
|
|
||||||
## 4) Note
|
Se gli archivi correnti sono gia presenti nella cartella `storage` del workspace, non serve alcun path esterno aggiuntivo: il container usera direttamente quello storage.
|
||||||
- Gli archivi legacy non sono inclusi nelle immagini Docker.
|
|
||||||
- Vengono montati in read-only da `LEGACY_ARCHIVES_PATH`.
|
Se invece gli archivi stanno fuori dal repository, puntare `NETGESCON_STORAGE_PATH` al path host reale.
|
||||||
- La migrazione DB viene eseguita all’avvio (entrypoint).
|
|
||||||
|
## 2) Validazione prima dell'avvio
|
||||||
|
|
||||||
|
Controllare che il compose risolva correttamente le variabili:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash docker/run-app-stack.sh config
|
||||||
|
```
|
||||||
|
|
||||||
|
Questo e il check piu economico per verificare:
|
||||||
|
|
||||||
|
- file env presente
|
||||||
|
- sostituzione variabili corretta
|
||||||
|
- bind mount storage/cache coerenti
|
||||||
|
- nessuna migrazione automatica indesiderata
|
||||||
|
|
||||||
|
## 3) Avvio stack
|
||||||
|
|
||||||
|
Avvio completo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash docker/run-app-stack.sh up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifica container:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash docker/run-app-stack.sh ps
|
||||||
|
```
|
||||||
|
|
||||||
|
Log applicazione:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash docker/run-app-stack.sh logs app --tail=200
|
||||||
|
```
|
||||||
|
|
||||||
|
Log nginx:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash docker/run-app-stack.sh logs nginx --tail=200
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4) Accesso e collaudo
|
||||||
|
|
||||||
|
URL locale/staging base:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://localhost:${APP_PORT}
|
||||||
|
```
|
||||||
|
|
||||||
|
Collaudi minimi dopo l'avvio:
|
||||||
|
|
||||||
|
1. login Filament
|
||||||
|
2. pagina `Servizi / Utenze`
|
||||||
|
3. verifica righe FE acqua con riferimento unico `CBILL`
|
||||||
|
4. pagina `Acquisizione Documenti`
|
||||||
|
5. lettore Datalogic con visualizzazione del testo etichetta archivio
|
||||||
|
|
||||||
|
## 5) Politica dati attuale
|
||||||
|
|
||||||
|
- DB esterno esistente: consentito
|
||||||
|
- archivi esistenti: consentiti
|
||||||
|
- migrazioni automatiche in avvio: disattivate di default
|
||||||
|
- `mailhog`: usato per test locale, non per invio ufficiale
|
||||||
|
|
||||||
|
## 6) Differenze rispetto ai documenti storici
|
||||||
|
|
||||||
|
I documenti storici che citano `docker/docker-compose.prod.yml`, `.env.docker.example` o mount legacy separati non sono piu il riferimento operativo principale per Day0.
|
||||||
|
|
||||||
|
Per Day0 fanno fede:
|
||||||
|
|
||||||
|
- `docker-compose.yml`
|
||||||
|
- `docker/run-app-stack.sh`
|
||||||
|
- `.env.docker.local.example`
|
||||||
|
- `.env.docker.local` locale non versionato
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user