Questa guida mostra un flusso pratico per avviare un ambiente Magento Open Source in locale usando Docker e Docker Compose, con servizi separati per web/PHP, database e caching, e con comandi ripetibili per installazione, aggiornamenti e operazioni quotidiane.
Obiettivi e approccio
- Isolare dipendenze (PHP, estensioni, MySQL/MariaDB, Elasticsearch/OpenSearch, Redis) in container.
- Persistenza dati tramite volumi Docker.
- Riproducibilità: stesso stack per tutti gli sviluppatori, CI e ambienti di test.
- Workflow: installazione, build static content, cache, indicizzazione, backup, troubleshooting.
Prerequisiti
- Docker Engine e Docker Compose v2 (plugin) installati.
- Git e un terminale.
- Accesso a un repository Magento o a un progetto già inizializzato.
- Credenziali per scaricare Magento via Composer (repo.magento.com): pubblica/privata (keys).
Struttura consigliata del progetto
Una struttura minimale e chiara aiuta a gestire configurazioni e persistenze.
mkdir -p magento-docker/{docker,magento}
cd magento-docker
Organizzazione tipica:
magento-docker/
docker/
php/
Dockerfile
php.ini
nginx/
default.conf
magento/ # codice sorgente Magento (bind mount)
docker-compose.yml
.env
File .env per variabili riusabili
Con Compose è comodo centralizzare porte, credenziali e hostname.
# .env
PROJECT_NAME=magento
HTTP_PORT=8080
DB_HOST=db
DB_NAME=magento
DB_USER=magento
DB_PASSWORD=magento
DB_ROOT_PASSWORD=root
REDIS_HOST=redis
ELASTIC_HOST=elasticsearch
# Utile per UID/GID se vuoi evitare problemi di permessi su Linux
APP_UID=1000
APP_GID=1000
Dockerfile PHP per Magento
Magento richiede estensioni PHP specifiche e Composer. La base dipende dalla versione di Magento; qui si mostra un esempio generico con PHP-FPM e pacchetti comuni. Adatta la versione PHP alla tua release Magento.
# docker/php/Dockerfile
FROM php:8.2-fpm
# Dipendenze di sistema e strumenti
RUN apt-get update && apt-get install -y --no-install-recommends \
git unzip libzip-dev libpng-dev libjpeg-dev libfreetype6-dev \
libicu-dev libxslt1-dev libonig-dev libxml2-dev \
libcurl4-openssl-dev libreadline-dev \
&& rm -rf /var/lib/apt/lists/*
# Estensioni PHP richieste (set minimo comune)
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) \
bcmath intl pdo_mysql soap xsl zip gd opcache sockets
# Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# Config PHP
COPY php.ini /usr/local/etc/php/conf.d/zz-magento.ini
WORKDIR /var/www/html
Esempio di file ini (valori tipici per sviluppo):
; docker/php/php.ini
memory_limit = 2G
max_execution_time = 1800
upload_max_filesize = 64M
post_max_size = 64M
date.timezone = Europe/Rome
; OpCache (sviluppo: spesso meglio disattivare o rendere "soft")
opcache.enable=1
opcache.validate_timestamps=1
opcache.revalidate_freq=0
Configurazione Nginx
Nginx espone l'app su una porta locale e inoltra le richieste PHP a PHP-FPM. Il document root deve puntare alla cartella pub/ di Magento.
# docker/nginx/default.conf
server {
listen 80;
server_name localhost;
root /var/www/html/pub;
index index.php;
# Magento: regole base
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass php:9000;
fastcgi_read_timeout 1800;
}
# Statici
location ~* \.(jpg|jpeg|gif|png|css|js|ico|svg|woff|woff2|ttf)$ {
expires 1d;
access_log off;
try_files $uri $uri/ /index.php?$args;
}
client_max_body_size 64M;
}
docker-compose.yml: stack di base
Lo stack seguente include:
- nginx come web server
- php come runtime applicativo (PHP-FPM + Composer)
- db (MariaDB) per persistenza dati
- redis per cache/sessioni
- elasticsearch per catalog search (o sostituiscilo con OpenSearch se richiesto dalla tua versione)
# docker-compose.yml
services:
nginx:
image: nginx:1.27-alpine
depends_on:
- php
ports:
- "${HTTP_PORT}:80"
volumes:
- ./magento:/var/www/html:delegated
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
php:
build:
context: ./docker/php
volumes:
- ./magento:/var/www/html:delegated
environment:
- PHP_MEMORY_LIMIT=2G
db:
image: mariadb:10.6
command: --max_allowed_packet=64M
environment:
- MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
- MARIADB_DATABASE=${DB_NAME}
- MARIADB_USER=${DB_USER}
- MARIADB_PASSWORD=${DB_PASSWORD}
volumes:
- dbdata:/var/lib/mysql
redis:
image: redis:7-alpine
volumes:
- redisdata:/data
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.22
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- ES_JAVA_OPTS=-Xms1g -Xmx1g
volumes:
- esdata:/usr/share/elasticsearch/data
volumes:
dbdata:
redisdata:
esdata:
Note pratiche:
- Le versioni dei container (MariaDB/Elasticsearch/PHP) vanno allineate alla tua versione Magento.
- Se sei su macOS/Windows, i bind mount possono essere più lenti. Valuta opzioni come
delegatedo soluzioni di sync. - Elasticsearch richiede spesso aumentare memoria/limiti del sistema (es.
vm.max_map_countsu Linux).
Avvio dello stack
docker compose up -d --build
docker compose ps
Verifica log in caso di problemi:
docker compose logs -f --tail=200 nginx
docker compose logs -f --tail=200 php
docker compose logs -f --tail=200 db
Ottenere il codice Magento nel volume bind
Hai due strade comuni:
- Progetto già esistente: clona nel path
./magento. - Nuova installazione via Composer: crea il progetto dentro
./magento.
Opzione A: clonare un repository
git clone <repo> magento
Opzione B: creare un nuovo progetto Magento con Composer
Se usi Composer dal container PHP, non installi nulla sul sistema host. Prima configura le chiavi Magento (una sola volta):
docker compose exec php composer config --global http-basic.repo.magento.com <PUBLIC_KEY> <PRIVATE_KEY>
Poi crea il progetto (adatta il package alla versione desiderata):
docker compose exec php bash -lc "composer create-project --repository=https://repo.magento.com/ magento/project-community-edition /var/www/html"
Se la cartella magento/ è vuota e montata su /var/www/html, il comando popolerà direttamente la directory sul tuo host.
Permessi file e utenti: evitare attriti
Magento scrive in var/, generated/, pub/static/ e app/etc. In sviluppo, un approccio comune è far girare PHP come utente che corrisponde al tuo UID/GID, oppure applicare permessi coerenti.
Esempio rapido (sviluppo):
docker compose exec php bash -lc "chown -R www-data:www-data var generated pub/static pub/media app/etc || true"
docker compose exec php bash -lc "find var generated pub/static pub/media app/etc -type d -exec chmod 775 {} \; || true"
docker compose exec php bash -lc "find var generated pub/static pub/media app/etc -type f -exec chmod 664 {} \; || true"
In ambienti di team su Linux conviene allineare UID/GID nel Dockerfile o via entrypoint, ma in locale questa soluzione spesso è sufficiente.
Installazione di Magento via CLI
Magento si installa tipicamente usando bin/magento setup:install. Ecco un esempio completo che usa i servizi del Compose.
docker compose exec php bash -lc "php -d memory_limit=-1 bin/magento setup:install --base-url=http://localhost:${HTTP_PORT}/ --db-host=${DB_HOST} --db-name=${DB_NAME} --db-user=${DB_USER} --db-password=${DB_PASSWORD} --admin-firstname=Admin --admin-lastname=User --admin-email=admin@example.com --admin-user=admin --admin-password='Admin12345!' --backend-frontname=admin --language=it_IT --currency=EUR --timezone=Europe/Rome --use-rewrites=1 --search-engine=elasticsearch7 --elasticsearch-host=${ELASTIC_HOST} --elasticsearch-port=9200 --session-save=redis --session-save-redis-host=${REDIS_HOST} --cache-backend=redis --cache-backend-redis-server=${REDIS_HOST} --cache-backend-redis-db=0"
Se la tua versione usa OpenSearch o un motore differente, cambia i flag relativi al search engine in base alla documentazione della tua release.
Post-install: comandi tipici di build
Dopo l'installazione, in sviluppo spesso conviene usare la modalità developer e rigenerare cache e contenuti statici quando necessario.
docker compose exec php bash -lc "bin/magento deploy:mode:set developer"
docker compose exec php bash -lc "bin/magento cache:flush"
docker compose exec php bash -lc "bin/magento indexer:reindex"
Per ambienti simili a staging/produzione (più lenti ma più fedeli):
docker compose exec php bash -lc "bin/magento deploy:mode:set production"
docker compose exec php bash -lc "bin/magento setup:di:compile"
docker compose exec php bash -lc "bin/magento setup:static-content:deploy -f it_IT en_US"
docker compose exec php bash -lc "bin/magento cache:flush"
Configurare host e URL
Con la compose sopra, Magento è raggiungibile su http://localhost:8080 (o la porta impostata). Se devi aggiornare base URL e secure URL:
docker compose exec php bash -lc "bin/magento config:set web/unsecure/base_url http://localhost:${HTTP_PORT}/"
docker compose exec php bash -lc "bin/magento config:set web/secure/base_url http://localhost:${HTTP_PORT}/"
docker compose exec php bash -lc "bin/magento cache:flush"
Workflow quotidiano con Docker Compose
Entrare nel container PHP
docker compose exec php bash
Eseguire comandi Magento
docker compose exec php bin/magento cache:status
docker compose exec php bin/magento cache:flush
docker compose exec php bin/magento indexer:status
docker compose exec php bin/magento indexer:reindex
Gestire Composer dipendenze
docker compose exec php composer install
docker compose exec php composer update vendor/package
Abilitare/disabilitare moduli
docker compose exec php bin/magento module:status
docker compose exec php bin/magento module:enable Vendor_Module
docker compose exec php bin/magento module:disable Vendor_Module
docker compose exec php bin/magento setup:upgrade
docker compose exec php bin/magento cache:flush
Import/export database e backup
Per fare un dump dal container DB verso il tuo host:
docker compose exec db bash -lc "mysqldump -uroot -p${DB_ROOT_PASSWORD} ${DB_NAME} > /tmp/db.sql"
docker cp $(docker compose ps -q db):/tmp/db.sql ./db.sql
Ripristino:
docker cp ./db.sql $(docker compose ps -q db):/tmp/db.sql
docker compose exec db bash -lc "mysql -uroot -p${DB_ROOT_PASSWORD} ${DB_NAME} < /tmp/db.sql"
Ottimizzazioni utili
Mailcatcher/Mailpit per email in locale
Per testare l'invio email senza spedire davvero, aggiungi un servizio come Mailpit e configura Magento/SMTP di conseguenza.
# Esempio (aggiunta a docker-compose.yml)
mailpit:
image: axllent/mailpit:latest
ports:
- "8025:8025" # UI
- "1025:1025" # SMTP
Varnish (opzionale)
Magento supporta Varnish come full-page cache. In sviluppo è spesso superfluo, ma può essere utile per test più realistici. Integrare Varnish richiede configurazione aggiuntiva (porte, backends, export della VCL da Magento).
Modalità developer e symlink statici
In developer mode, molte risorse vengono gestite in modo più dinamico, riducendo la necessità di deploy statico ad ogni modifica. Se lavori spesso su frontend, questo migliora la velocità del ciclo modifica-verifica.
Troubleshooting: problemi comuni e soluzioni
Elasticsearch non parte o va in crash
- Su Linux, verifica
vm.max_map_count(spesso deve essere almeno 262144). - Aumenta
ES_JAVA_OPTSse hai dataset grandi; riducilo se hai poca RAM. - Controlla i log:
docker compose logs -f elasticsearch.
Errori 502/504 su Nginx
- PHP-FPM non risponde: controlla
docker compose logs -f php. - Timeout durante install/compile: aumenta
fastcgi_read_timeoutemax_execution_time. - Permessi: Magento può bloccarsi se non riesce a scrivere in
var/egenerated/.
Schermata bianca o assets mancanti
- Pulisci cache e static content:
bin/magento cache:flush. - In produzione, riesegui:
setup:static-content:deploy. - Verifica che il document root sia
pub/e che Nginx serva correttamente gli statici.
Problemi di performance su macOS/Windows
- Riduci il numero di bind mount, usa volumi per
vendor/o caching dove possibile. - Abilita caching Composer e usa
composer installcon cache persistente. - Considera un filesystem di sync (a seconda della tua toolchain) per migliorare I/O.
Comandi rapidi di riferimento
# Build e avvio
docker compose up -d --build
# Stop e rimozione container (conserva volumi)
docker compose down
# Stop e rimozione anche dei volumi (ATTENZIONE: elimina DB e dati ES/Redis)
docker compose down -v
# Logs
docker compose logs -f --tail=200
# Magento CLI
docker compose exec php bin/magento cache:flush
docker compose exec php bin/magento indexer:reindex
Conclusione
Con Docker e Docker Compose puoi ottenere un ambiente Magento ripetibile e controllato, riducendo drasticamente i problemi legati a versioni di PHP/servizi e rendendo più lineare il lavoro in team. La chiave è allineare le versioni dei servizi alla tua release Magento, mantenere volumi per la persistenza e trasformare le operazioni comuni (install, upgrade, compile, deploy) in comandi standardizzati eseguibili dal container PHP.