Semplifica il deploy: un solo docker-compose senza anchor YAML

I due file compose andavano tenuti allineati a mano, e gli anchor
(x-app-env, <<:) sono sintassi che va conosciuta per riuscire a leggere il
file. Per un deploy che deve restare semplice era complessita' non
giustificata.

Ora c'e' un solo docker-compose.yml, esplicito, che copre produzione e
sviluppo:

- ogni servizio dichiara quello che usa, senza merge key
- mailpit e' dietro il profilo "dev", quindi non parte mai in produzione
- la porta e' legata a 127.0.0.1 per default: in produzione il traffico
  arriva da Traefik sulla rete interna, in locale basta localhost:8080.
  Per esporla davvero: APP_PORT=0.0.0.0:8080
- .env diventa l'unica fonte di configurazione, senza valori ridichiarati

Compromesso accettato: sparendo i valori fissati nel compose, DB_HOST e
REDIS_HOST devono contenere i nomi dei servizi (mariadb, redis) e non un
indirizzo. E' segnalato in .env.example, nel README e in HANDOFF.md.

Per le modifiche al codice senza ricostruire l'immagine il README documenta
un docker-compose.override.yml, che Compose applica da solo ed e' gia'
ignorato da git.

Verificato: sei servizi healthy, login e pagine a 200, redeploy idempotente,
porta esposta solo su localhost, mailpit assente senza il profilo dev.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-19 17:41:48 +02:00
parent 0502fad996
commit afaaeb5927
5 changed files with 232 additions and 318 deletions

126
README.md
View File

@@ -102,17 +102,29 @@ DB_PASSWORD=...
DB_ROOT_PASSWORD=...
REDIS_PASSWORD=...
# --- Database ---
# --- Database (mariadb e' il nome del servizio, non cambiarlo) ---
DB_CONNECTION=mysql
DB_HOST=mariadb
DB_PORT=3306
DB_DATABASE=termanager2
DB_USERNAME=termanager2
# --- Redis (idem: redis e' il nome del servizio) ---
REDIS_HOST=redis
REDIS_PORT=6379
CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
# --- Primo amministratore (creato al primo avvio) ---
INITIAL_ADMIN_NAME=Nome Cognome
INITIAL_ADMIN_EMAIL=admin@tuodominio.it
INITIAL_ADMIN_PASSWORD=UnaPasswordSolida
# --- Sessioni ---
# --- Sessioni e log ---
SESSION_SECURE_COOKIE=true
LOG_CHANNEL=stderr
LOG_LEVEL=warning
# --- Posta (SMTP esterno) ---
MAIL_MAILER=smtp
@@ -186,63 +198,84 @@ Lo stack è Docker Compose standard e funziona su **Coolify**, **Portainer**,
Le uniche due particolarità sono:
1. **La rete `dokploy-network`.** In fondo a `docker-compose.yml` c'è una rete
esterna che serve al Traefik di Dokploy per raggiungere il container. Su
altri sistemi rimuovila e pubblica una porta:
1. **Il file `.env`.** Dokploy lo genera dalle variabili della sua interfaccia.
Altrove crealo a mano: `cp .env.example .env` e compila i valori.
```yaml
services:
app:
ports:
- "8080:80"
networks:
- internal # rimuovi "- dokploy-network"
2. **La rete `dokploy-network`.** In fondo a `docker-compose.yml` c'è una rete
esterna che serve al Traefik di Dokploy per raggiungere il container. Hai
due possibilità:
networks:
internal:
driver: bridge
# rimuovi il blocco dokploy-network
```
- **Tenerla**, creandola una volta sola:
`docker network create dokploy-network`
- **Rimuoverla**: elimina `- dokploy-network` dalle reti del servizio `app`
e il blocco `dokploy-network:` in fondo al file.
Poi metti il tuo reverse proxy (Nginx, Caddy, Traefik) davanti alla porta
`8080`, con certificato TLS.
2. **Il file `.env`.** Dokploy lo genera dalle variabili della sua interfaccia.
Altrove crealo a mano nella cartella del progetto, con lo stesso contenuto
del [Passo 3](#passo-3--imposta-le-variabili-dambiente).
Dopodiché:
Poi imposta nel `.env` la porta su cui esporre l'applicazione e avvia:
```bash
# ascolta su tutte le interfacce, per metterci davanti un reverse proxy
echo "APP_PORT=0.0.0.0:8080" >> .env
docker compose up -d --build
docker compose logs -f app
```
Infine metti il tuo reverse proxy (Nginx, Caddy, Traefik) davanti alla porta
`8080`, con certificato TLS.
---
## Sviluppo locale
Si usa lo stesso `docker-compose.yml` della produzione, con il profilo `dev`
che aggiunge Mailpit:
```bash
cp .env.example .env
docker compose -f docker-compose.dev.yml up -d --build
docker network create dokploy-network # una volta sola
# nel .env, per l'uso locale:
# APP_URL=http://localhost:8080
# APP_ENV=local
# SESSION_SECURE_COOKIE=false
# MAIL_MAILER=smtp MAIL_HOST=mailpit MAIL_PORT=1025
# e le tre password a piacere
docker compose --profile dev up -d --build
```
| Cosa | Dove |
|---------------------|-------------------------------|
| Applicazione | http://localhost:8080 |
| Mailpit (posta test)| http://localhost:8025 |
| Login | `admin@termanager2.local` / `password` |
| Login | quello che hai messo in `INITIAL_ADMIN_*` |
A differenza della produzione, l'ambiente di sviluppo monta il codice sorgente
in bind mount — le modifiche PHP sono immediate — e pubblica le porte
sull'host.
Se la porta 8080 è occupata, cambia `APP_PORT` nel `.env`
(es. `APP_PORT=127.0.0.1:8081`).
Se la porta 8080 è occupata:
### Modifiche al codice senza ricostruire l'immagine
```bash
APP_PORT=8081 docker compose -f docker-compose.dev.yml up -d
L'immagine è autosufficiente: `vendor/` e `public/build` stanno dentro, quindi
di norma una modifica al codice richiede `docker compose up -d --build`.
Per avere invece le modifiche PHP immediate, crea un
`docker-compose.override.yml` — Docker Compose lo applica da solo, senza
bisogno di alcun flag:
```yaml
services:
app:
environment:
PHP_OPCACHE_VALIDATE_TIMESTAMPS: 1
volumes:
- ./:/var/www/html
# vendor e build restano quelli dell'immagine, non quelli dell'host
- /var/www/html/vendor
- /var/www/html/public/build
```
Il file è già in `.gitignore`, quindi resta solo tuo.
Per lavorare sugli asset frontend con hot reload:
```bash
@@ -285,15 +318,20 @@ ridichiara le variabili applicative: le prende dal `.env` così com'è.
| `RUN_MIGRATIONS` | `true` | Migrazioni automatiche all'avvio |
| `RUN_DB_SEED_ON_FIRST_START` | `true` | Seed al primo avvio |
### Fissate dal compose
### Da non cambiare
Questi valori sono imposti da `docker-compose.yml` e **ignorano** quanto scritto
nel `.env`, perché descrivono la topologia dello stack: `DB_HOST`, `DB_PORT`,
`REDIS_HOST`, `REDIS_PORT`, `CACHE_STORE`, `SESSION_DRIVER`,
`QUEUE_CONNECTION`, `LOG_CHANNEL`.
Questi valori sono **nomi di servizi** definiti in `docker-compose.yml`, non
indirizzi di rete. Se li modifichi il container non trova più il database o
Redis:
Serve a evitare che un `.env` copiato da una macchina di sviluppo (con, per
dire, `DB_HOST=127.0.0.1`) rompa il container.
```dotenv
DB_HOST=mariadb
REDIS_HOST=redis
```
Nemmeno `CACHE_STORE`, `SESSION_DRIVER` e `QUEUE_CONNECTION` andrebbero
spostati altrove: lo stack fornisce Redis e il queue worker consuma la coda
Redis, quindi puntarli su un driver diverso interrompe l'elaborazione dei job.
---
@@ -451,8 +489,8 @@ cifrati).
### Reset completo (solo sviluppo)
```bash
docker compose -f docker-compose.dev.yml down -v
docker compose -f docker-compose.dev.yml up -d --build
docker compose --profile dev down -v
docker compose --profile dev up -d --build
```
`-v` cancella i volumi: database, Redis e file caricati vengono persi.
@@ -673,8 +711,8 @@ TerManager2/
│ └── supervisor/ # nginx + php-fpm nello stesso container
├── resources/ # CSS, JS, viste Blade
├── routes/web.php # Rotte con i relativi permessi
├── docker-compose.yml # Produzione
├── docker-compose.dev.yml # Sviluppo locale
├── docker-compose.yml # Unico, produzione e sviluppo
├── .env.example # Tutta la configurazione
├── HANDOFF.md # Stato del progetto per chi subentra
└── README.md
```