Vai al contenuto
Home / Blog /Tutorial / Sviluppo locale di Maho con Harbor

Sviluppo locale di Maho con Harbor

Avvia da zero un ambiente di sviluppo Maho completo con Harbor e scopri come usarlo ogni giorno: FrankenPHP, MySQL 8.4, Mailpit, cron, profili opzionali e personalizzazioni, tutto da un unico launcher Docker Compose.

Read in English

Immagina un porto in cui la tua nave è già in acqua, equipaggiata e pronta a salpare. Non hai montato banchine, gru o fari: li ha messi in piedi qualcun altro per te. Questo è Harbor, il launcher Docker Compose e lo stack di sviluppo per Maho: un progetto open source di MageMEGA, ispirato a Laravel Sail, usato in casa e donato alla community. Con un pugno di comandi costruisci l’intero ambiente: l’app (FrankenPHP con Caddy e PHP), un database MySQL 8.4, Mailpit per le mail in uscita e Ofelia per il cron. Il binario harbor fa da wrapper a docker compose, quindi non devi mai scrivere a mano né il file compose né i comandi docker compose che ne derivano. Harbor conosce il file generato, i profili e i nomi dei servizi al posto tuo e ti offre comandi brevi. Concretamente:

# quello che dovresti digitare a mano ogni volta...
docker compose -f .harbor/compose.yaml exec app php ./maho cache:flush
docker compose -f .harbor/compose.yaml exec app bash

# ...diventa semplicemente
./vendor/bin/harbor maho cache:flush
./vendor/bin/harbor shell

⚓ Nota di bordo. Harbor è un porto, non il mare aperto. In produzione affonderebbe: il suo stesso README ne vieta l’uso. Qui siamo in rada, al sicuro, con la libertà di speronare tutto e ricostruire da zero quando serve.

Requisiti

Sulla macchina host servono:

  • Docker con il plugin Compose v2 (Harbor preferisce docker compose e ripiega su docker-compose).
  • PHP >= 8.3, solo per eseguire Composer con create-project e require. Tutto il resto vive nel container, che monta PHP 8.4 di default.

Quick start: dallo zero allo store in funzione

1. Crea il progetto

Parti dallo starter ufficiale e aggiungi Harbor come dipendenza di sviluppo:

composer create-project mahocommerce/maho-starter my-store
cd my-store
composer require --dev empiricompany/harbor   # oppure :dev-main per l'ultima versione

2. Inizializza e avvia lo stack

harbor init genera la cartella .harbor/ con i file del progetto: .env, compose.yaml, docker.override.yaml e docker.install.yaml (questi ultimi due partono vuoti). Poi costruisci e avvia lo stack. La prima build richiede dai 5 ai 20 minuti: il momento giusto per farsi un caffè, non per premere Ctrl+C.

./vendor/bin/harbor init
./vendor/bin/harbor up -d --build
./vendor/bin/harbor ps

--build serve ogni volta che cambi il Dockerfile o le estensioni PHP dell’immagine. ps conferma che i container siano attivi.

3. Installa le dipendenze e Maho

Installa le dipendenze PHP dentro il container dell’app, poi lancia l’installer di Maho:

./vendor/bin/harbor composer install

./vendor/bin/harbor maho install --license_agreement_accepted yes \
  --locale it_IT --timezone Europe/Rome --default_currency EUR \
  --db_host db --db_name maho --db_user maho --db_pass maho \
  --url 'https://localhost:8443/' --use_secure 1 --secure_base_url 'https://localhost:8443/' \
  --use_secure_admin 1 --admin_username admin --admin_password 'cambiami-forte' \
  --sample_data 1

Una nota su --url: deve combaciare con l’URL configurato in Harbor. Se i due valori non coincidono, Maho salva i base URL puntati altrove e ogni link generato si rompe.

4. Reindex, cache e primo accesso

Chiudi con un reindex e uno svuotamento della cache, poi apri lo store:

./vendor/bin/harbor maho index:reindex:all && ./vendor/bin/harbor maho cache:flush
./vendor/bin/harbor open admin

Lo storefront ora è su https://localhost:8443/ (HTTPS, con la CA interna di Caddy o un certificato self-signed). harbor open apre nel browser l’admin o Mailpit (open mailpit). Per accorciare i comandi puoi aggiungere un alias alla tua shell:

alias harbor='./vendor/bin/harbor'

Come si usa Harbor

Lancia harbor dalla root del progetto: i comandi girano nel container, quindi non devi installare nulla dell’applicazione sulla tua macchina. harbor composer e harbor maho coprono quasi tutto il lavoro quotidiano, e qualsiasi comando che Harbor non riconosce viene passato direttamente a Docker Compose. In pratica non impari un nuovo strumento: parli al tuo Docker Compose, ma con un maggiordomo che lo traduce.

Ciclo di vita e diagnostica

./vendor/bin/harbor up -d [--build]     # avvia (e ricostruisce) lo stack
./vendor/bin/harbor ps                  # stato dei container
./vendor/bin/harbor logs -f app         # log in streaming
./vendor/bin/harbor stop [servizio]     # ferma
./vendor/bin/harbor restart [servizio]  # riavvia
./vendor/bin/harbor down                # ferma e rimuove container e reti
./vendor/bin/harbor config              # mostra la configurazione Compose finale
./vendor/bin/harbor doctor              # valida Docker, Compose e lo stack

down -v è distruttivo: rimuove anche i volumi, quindi il database viene azzerato. L’app scrive sia l’access log di Caddy sia gli errori PHP su stdout/stderr, quindi tutto arriva in un unico flusso con logs app.

⚓ Nota di bordo. down -v è il tasto che affonda la nave con tutto l’equipaggio, database compreso. Prima di premerlo esporta un backup con harbor maho db:export: il porto si ricostruisce, i dati no.

Quando ti serve entrare nei container:

./vendor/bin/harbor shell               # bash nel container app
./vendor/bin/harbor shell --service db  # bash in un altro servizio
./vendor/bin/harbor root-shell          # bash come root in app
./vendor/bin/harbor exec --service app php -v
./vendor/bin/harbor mysql maho --execute='SHOW TABLES'
./vendor/bin/harbor redis --raw ping

Per le query preferisci harbor maho db:query; harbor mysql è per il lavoro grezzo o interattivo con il client.

Composer e la CLI di Maho

Composer passa attraverso Harbor con un passthrough completo (install, update, require, remove e così via):

./vendor/bin/harbor composer update
./vendor/bin/harbor composer require vendor/package

harbor composer update reinstalla i package locali a path e ripubblica gli asset dei moduli in public/. Se modifichi un file sotto il public/ di un package, rilancia composer update per ripubblicarlo.

La CLI di Maho è harbor maho <comando> e legge le credenziali da app/etc/local.xml. I comandi che userai di più:

  • migrate: applica gli aggiornamenti dichiarativi di schema e dati. Lancialo dopo aver installato un modulo o modificato i suoi script di setup.
  • cache:flush: obbligatorio dopo aver rinominato blocchi, layout handle o alias di configurazione. La cache di layout e config sopravvive alle modifiche dei file e continua a servire XML vecchio.
  • db:query "SELECT ...": il modo giusto per fare SQL, perché legge le credenziali da local.xml. Comodo per verificare core_resource e le personalizzazioni in core_config_data.
  • config:get|set|delete <path>: leggi e scrivi i valori di core_config_data risolvendo per te gli scope. Preferiscili a SQL scritto a mano.
  • db:export / db:import: dump e restore del database. Indica la compressione con --compression=gzip|zstd e usa --drop-tables per ricreare il database prima di importare.
  • health-check, admin:user:*, shell, accessibility:scan: diagnostica, gestione degli admin, PHP shell con Maho avviato e scansione di accessibilità.

Un ciclo tipico per installare o aggiornare un modulo locale e verificarne il setup:

./vendor/bin/harbor composer update
./vendor/bin/harbor maho migrate
./vendor/bin/harbor maho db:query "SELECT * FROM core_resource WHERE code LIKE '%<alias>%'"
./vendor/bin/harbor maho cache:flush

Per riportare lo store a uno stato noto:

./vendor/bin/harbor maho db:export var/backups/backup.sql.gz --compression=gzip
./vendor/bin/harbor maho db:import var/backups/backup.sql.gz --compression=gzip --drop-tables
./vendor/bin/harbor maho cache:flush

Servizi opzionali e profili

Lo stack di base contiene quattro container: app, db, mailpit e cron. I servizi opzionali si gestiscono con i profili, elencati in .harbor/.env.

Profili inclusi:

  • redis: server Redis su redis:6379 (dall’host 127.0.0.1:6379), con database separati per sessioni e cache.
  • adminer: web UI su http://localhost:8082, con il server db già precompilato.
  • phpmyadmin: web UI su http://localhost:8081, con accesso automatico alle credenziali del database.
  • cloudflared e cloudflared-quick: tunnel Cloudflare, descritti più avanti.
./vendor/bin/harbor services list
./vendor/bin/harbor services add phpmyadmin   # oppure redis, adminer, cloudflared
./vendor/bin/harbor services add redis
./vendor/bin/harbor up -d     # applica il cambio di profilo
./vendor/bin/harbor ps        # verifica

services add e services remove aggiornano solo .harbor/.env: non avviano né fermano container. È anche il meccanismo per personalizzare lo stack: dichiari un servizio con profiles: [nome] in .harbor/docker.override.yaml e Harbor lo scopre e lo gestisce come i profili inclusi. Se ometti del tutto la chiave profiles, il servizio entra nello stack di default e parte a ogni up.

Mail, cron e tunnel

Mailpit è un servizio di base, sempre attivo: è un SMTP catch-all, quindi tutte le email dello store restano in locale. La UI è su http://localhost:8025. Dall’host la porta SMTP è localhost:1025, mentre le applicazioni nei container inviano a mailpit:1025. Mailpit non ha autenticazione: non esporlo mai.

⚓ Nota di bordo. Mailpit intercetta ogni mail in uscita del porto: la trattiene invece di spedirla al mondo. Perfetto per testare conferme d’ordine e newsletter senza spammare clienti veri.

Il servizio cron esegue Ofelia, che pianifica i job di Maho attraverso label Docker. Va avviato esplicitamente:

./vendor/bin/harbor cron

Due job sono definiti di default: maho-cron-always ogni minuto (cron:run always) e maho-cron-default ogni cinque minuti (cron:run default), entrambi senza sovrapposizione. Se non avvii Ofelia, i job di Maho restano a dormire. Per aggiungere job tuoi usa le label ofelia.job-exec.<nome>.* in .harbor/docker.override.yaml, poi up -d per ricreare il servizio e logs cron per controllare.

Se ti serve esporre lo store fuori dalla tua macchina senza aprire porte, Harbor ha i profili Cloudflare Tunnel:

./vendor/bin/harbor tunnel quick --autoconfig   # URL effimero *.trycloudflare.com
./vendor/bin/harbor tunnel down --autoconfig    # ripristina l'URL locale

--autoconfig punta i base URL di Maho all’URL pubblico e li ripristina alla chiusura.

Configurazione: cosa modificare e dove

Il file generato .harbor/compose.yaml non va mai modificato a mano. Le tue modifiche locali vanno in .harbor/docker.override.yaml (oppure .harbor/docker.install.yaml), che Harbor unisce a quelle generate.

Solo per cambiare i binding delle porte serve toccare gli stub in .harbor/stubs/: tienili allineati con vendor/empiricompany/harbor/resources/stubs/ quando aggiorni Harbor.

Due ricette pratiche per iniziare.

Abilitare la developer mode

# .harbor/docker.override.yaml, unito sopra il compose.yaml generato
services:
  app:
    environment:
      MAGE_IS_DEVELOPER_MODE: "1"

Applica la modifica con ./vendor/bin/harbor up -d: Maho passa in developer mode, con il logging e la gestione degli errori più verbosi che servono mentre sviluppi.

Aggiungere un servizio allo stack

Nel file di override puoi dichiarare un servizio tu stesso. Con la chiave profiles diventa opzionale e Harbor lo scopre e lo gestisce come i profili inclusi. L’esempio aggiunge phpRedisAdmin, la web UI per Redis (richiede che anche il profilo redis sia attivo, per avere il server a cui connettersi):

# .harbor/docker.override.yaml
services:
  # phpRedisAdmin: web UI per Redis (profilo opzionale). Richiede il profilo
  # "redis" attivo per avere il server Redis a cui connettersi.
  phpredisadmin:
    image: erikdubbelboer/phpredisadmin:latest
    profiles: [phpredisadmin]
    environment:
      REDIS_1_HOST: "${HARBOR_REDIS_HOST:-redis}"
      REDIS_1_PORT: "${HARBOR_REDIS_PORT:-6379}"
    ports:
      - "${HARBOR_PHPREDISADMIN_PORT:-8084}:80"
    networks:
      - harbor

Poi abilita i profili e avvia:

./vendor/bin/harbor services add redis
./vendor/bin/harbor services add phpredisadmin
./vendor/bin/harbor up -d

La UI è su http://localhost:8084. Se invece togli del tutto la chiave profiles, il servizio entra nello stack di default e parte a ogni up.

Queste sono solo le basi. La guida completa, con tutti i comandi e le opzioni, è nel README di Harbor: https://github.com/empiricompany/harbor.

VS Code e Dev Container

Harbor genera la configurazione Dev Container con un solo comando:

./vendor/bin/harbor devcontainer --force

Scrive .devcontainer/devcontainer.json: punta a ../.harbor/compose.yaml, apre il servizio app e usa /app come workspace. Con l’estensione Dev Containers di VS Code, quando apri il progetto compare la richiesta di riaprire nel container. La configurazione installa anche l’estensione Maho per VS Code.

Per far usare a quell’estensione il PHP del container, aggiungi in .vscode/settings.json:

{
  "maho.phpCommand": "./vendor/bin/harbor php"
}

Così ogni comando PHP dell’estensione passa da Harbor e gira dove gira Maho, senza dover installare PHP sull’host.

Debug con Xdebug

Xdebug è già incluso nell’immagine dell’app: si accende da .harbor/.env.

HARBOR_XDEBUG_MODE=debug

Xdebug si ricollega all’IDE sulla porta 9003. Per verificare che sia attivo:

./vendor/bin/harbor php -m | grep -i '^xdebug$'
./vendor/bin/harbor php -i | grep -E 'xdebug.mode|xdebug.client'

In VS Code, con l’estensione PHP Debug, la configurazione di lancio mappa /app sulla root del progetto:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Listen for Xdebug",
      "type": "php",
      "request": "launch",
      "port": 9003,
      "pathMappings": { "/app": "${workspaceFolder}" }
    }
  ]
}

Avvia “Listen for Xdebug” (F5), metti un breakpoint e lancia ./vendor/bin/harbor debug script.php, oppure apri una pagina nel browser. Su un host remoto la combinazione più pulita è VS Code Remote-SSH con harbor devcontainer --force: l’extension host gira sul server e la porta 9003 è raggiungibile senza tunnel aggiuntivi.

Altre funzionalità di Harbor

  • MCP server di Maho: Harbor lo avvia su stdio, così i client AI compatibili possono dialogare con lo store. Nella configurazione del client:

    {
      "mcpServers": {
        "maho-stdio": {
          "command": "./vendor/bin/harbor",
          "args": ["maho", "dev:mcp:start"]
        }
      }
    }
  • Scansione di accessibilità: installa il runtime Playwright una volta con ./vendor/bin/harbor maho accessibility:install, poi analizza una pagina con ./vendor/bin/harbor maho accessibility:scan https://localhost:8443/.

  • Strumenti di qualità: ./vendor/bin/harbor test, ./vendor/bin/harbor phpunit e ./vendor/bin/harbor phpstan girano dentro il container, come harbor php e harbor bin.

  • Apertura rapida: ./vendor/bin/harbor open apre la UI; open admin e open mailpit le pagine corrispondenti.

  • Esperienza di sviluppo: empiricompany/maho-ignition aggiunge pagine d’errore illuminate, con eventuali soluzioni generate, e composer require intervention/image-driver-vips abilita l’elaborazione immagini ad alte prestazioni. Entrambi sono opzionali.

Troubleshooting rapido

./vendor/bin/harbor config      # verifica la configurazione Compose effettiva
./vendor/bin/harbor doctor      # valida Docker, Compose e lo stack
./vendor/bin/harbor ps          # controlla cosa sta girando
./vendor/bin/harbor logs app    # errori PHP e access log di Caddy
./vendor/bin/harbor logs cron   # job pianificati

Esegui sempre il launcher dalla cartella che contiene vendor/, .harbor/ e i file del progetto Maho.

⚓ Ultima nota di bordo. Il porto è pronto e le banchine pure. Alza il braccio, dai corrente e lascia che Harbor si occupi della logistica: alle tue idee resta solo il mare da esplorare. Buon vento!

Nota di redazione.Testo preparato con l'aiuto dell'AI e verificato sulla fonte prima della pubblicazione. Può contenere errori: se ne trovi uno, segnalalo.Leggi il Manifesto

Il tuo negozio vende ancora?

Raccontaci da dove parti: ti rispondiamo con una prima valutazione, senza impegno.

Chiedi l'analisi del negozio