A starter template for zdev that scaffolds a Shopware 6 project with a working local development environment.
- PHP 8.4 via ScaleCommerce's prebuilt
docker-php-cliimage (ghcr.io/scalecommerce/docker-php-cli:8.4.20), which ships with every extension Shopware requires (intl,pdo_mysql,gd,bcmath,opcache,exif,zip, plusapcu,redis,memcached, etc.), Composer, Node.js, npm, and pnpm already baked in — no runtime extension install - zpinit as PID 1 in supervise mode, running two supervised services: the Symfony CLI dev server and the Messenger worker. A crash of either keeps the container up and recoverable (
zdev execstill works) - The Symfony CLI and
shopware-clibaked into.zdev/Dockerfile— no runtime downloads. Bakingshopware-cliin particular avoids fetching it from GitHub's latest-release endpoint on every boot (which risks GitHub API rate limits) - MariaDB 11.4 LTS database (Shopware's recommended database — the Shopware team tests against MariaDB, and 11.4 is comfortably above the minimum 10.11 required by 6.7)
shopware/productionscaffolded once at create time viacomposer create-project shopware/production(the official Shopware 6 project skeleton)- Database schema, basic sales channel, and default admin user installed via
bin/console system:install --create-database --basic-setupon first boot (guarded by a marker, so it runs once per fresh database and never wipes an initialized one) shopware/dev-toolsadded as a dev dependency at create time (required forbin/console framework:demodata)- Demo data pre-generated on first boot (best-effort) so the storefront looks populated out of the box
- Administration First Run Wizard skipped via
bin/console system:config:set core.frw.completedAt— log in to/adminand go straight to the dashboard - Full asset build (admin + storefront + theme + bundle assets) run once on first boot via
shopware-cli project ci— a single command that wraps the admin/storefront JS builds,theme:compile, andassets:install - HTTPS via zdev's shared Traefik router, with
SYMFONY_TRUSTED_PROXIES=private_rangesso Symfony generateshttps://URLs behind the reverse proxy (without this, the admin login bounces and mixed-content errors appear in the browser console) - Permanent Symfony Messenger worker as a zpinit-supervised service in the app container — consumes the
asyncandlow_prioritytransports so emails, indexer updates, flow actions, and scheduled tasks process without anyone having to keep the admin tab open. zpinit respawns it every 120s (--time-limit, to pick up code changes) and on memory pressure (--memory-limit=512M). Same container as the dev server, so no parallel Mutagen session or composer install. Its log goes to/tmp/worker.log; inspect viazdev worker(see below) - Mailpit integration (
MAILER_DSN=smtp://mail:1025) — all outgoing mail is caught - OpenSearch disabled by default (
SHOPWARE_ES_ENABLED=0) — Shopware falls back to SQL-based search, which is plenty for dev - Mutagen file sync (macOS) with
vendor/,var/,node_modules/,public/bundles/,public/theme/,public/media/,public/thumbnail/, and.zdev/kept inside the container for speed
zdev create shopware my-shop
cd my-shop
zdev startzdev create scaffolds the project (a few minutes: composer create-project + dev-tools). The
first zdev start builds the image, installs deps, initializes the database, generates demo data,
and builds the admin + storefront assets — also several minutes. When it finishes, the shop is
running at https://my-shop.0ploy.dev.
- Storefront:
https://my-shop.0ploy.dev/ - Admin panel:
https://my-shop.0ploy.dev/admin/- Username:
admin - Password:
shopware
- Username:
At create time, zdev create runs .zdev/scaffold.sh once, in a throwaway
container (no DB service): it scaffolds Shopware via composer create-project shopware/production,
adds shopware/dev-tools, and copies the source into your project (not vendor/, which installs at
boot). After it succeeds, zdev renames the hook to .zdev/scaffold.sh.disabled.
On every boot, zpinit runs the steps in .zdev/zpinit/entrypoint.d/ and then supervises the dev server + worker:
10-install.sh—composer install(a no-op oncevendor/is populated).20-database.sh— waits for MariaDB, then once (guarded by avar/marker):system:install --create-database --basic-setup,framework:demodata(best-effort), skips the First Run Wizard, anddal:refresh:index. The guard is set right aftersystem:installso a later hiccup can never trigger a re-install that wipes data. It also means a teammate's firstzdev startafter cloning Just Works — their fresh DB gets initialized.30-assets.sh—shopware-cli project ci --with-dev-dependenciesonce (guarded by a marker), building the admin + storefront assets.
Because both the server and worker are supervised, a crash keeps the container up: zdev exec still
works, zpctl status shows service state, and zpctl restart app / zpctl restart worker recover
them after a fix.
Edit files in src/, custom/plugins/, or config/ and refresh the browser — Symfony reloads on every request in dev mode. Administration and storefront JS changes require a rebuild (see below).
The template ships zdev wrappers for the most common operations:
zdev cache-clear # = zdev console cache:clear
zdev refresh-index # = zdev console dal:refresh:index
zdev build # = zdev shopware-cli project ci --with-dev-dependencies
zdev console # bin/console with no args (lists every command)
zdev console cache:clear # any bin/console command — colons pass through
zdev console dal:refresh:index
zdev console plugin:refresh
zdev shopware-cli # shopware-cli top-level help
zdev shopware-cli project ci
zdev shopware-cli project doctor
zdev shopware-cli project storefront-watch # HMR watcher
zdev shopware-cli extension list
zdev worker # queue depth (async/low_priority/failed) + live worker pids
zdev worker drain # one-shot drain of the queue (useful after bulk imports)
zdev worker logs # tail the worker's log (/tmp/worker.log inside the container)
zdev worker failed # show messages stuck in the failure transport
zdev worker retry # retry every failed message
zdev worker restart # restart the supervised worker (zpctl restart worker)zdev shopware-cli project ci --with-dev-dependencies # Full rebuild (admin + storefront + theme + assets)
zdev shopware-cli project storefront-build # Rebuild storefront only
zdev shopware-cli project admin-build # Rebuild admin only
zdev shopware-cli project dump --output /app/dump.sql # DB dump (optionally --anonymize)
zdev shopware-cli project admin-api GET /api/product # Pre-authenticated Admin API call
zdev shopware-cli project doctor # Health-check the project
zdev exec app composer require <package> # Add a PHP package
zdev exec app composer update # Update composer packages
zdev console <command> # Run any Shopware / Symfony console command
zdev console cache:clear # Clear the cache
zdev console plugin:refresh # Refresh the plugin list
zdev console plugin:install --activate <Name> # Install + activate a plugin
zdev console theme:compile # Recompile the active theme (SCSS changes)
zdev console dal:refresh:index # Rebuild search/category indexes
zdev exec app bash -c "APP_ENV=prod php bin/console framework:demodata --products=50 --reset-defaults" # Regenerate demo data (needs APP_ENV=prod)
zdev exec app bash # Open an interactive shellshopware-cli is preinstalled in the container. Run zdev shopware-cli project --help for the full list.
Works out of the box (no project config needed):
| Command | What it does |
|---|---|
project ci [--with-dev-dependencies] |
One-shot build: composer install + admin-build + storefront-build + theme:compile + assets:install |
project admin-build / project storefront-build |
Individual Webpack/Vite builds |
project admin-watch / project storefront-watch |
Dev watchers with HMR (alternative to full rebuilds) |
project doctor |
Project health check (finds common misconfigurations) |
project extension install/activate/deactivate |
Wraps bin/console plugin:* with less ceremony |
project worker [amount] |
Runs Symfony workers (mail queue, flow actions, scheduled tasks) in the background |
project generate-jwt |
Rotates the JWT secret used for Admin API tokens |
Need .shopware-project.yml — run zdev shopware-cli project config init interactively once to create it, then:
| Command | What it does |
|---|---|
project admin-api [METHOD] [PATH] |
Auth'd curl to the Admin API — no manual token juggling |
project dump --anonymize --compression zstd |
DB dump with customer data scrubbed |
project clear-cache |
Clears the shop cache via the Admin API (for local, bin/console cache:clear is simpler) |
shopware-cli doesn't wrap system:install, framework:demodata, or system:config:set core.frw.completedAt — those stay on bin/console.
zdev db— opens Adminer. Connect with serverdb, userroot, passwordshopware, databaseshopware.zdev mail— opens Mailpit. All outgoing mail shows up here.zdev logs -f app— follow app container logs.zdev update— apply.zdev/config.yamlchanges (env, image, command, volumes).zdev restartalone won't — it preserves the container.
- Change DB password / name in
.zdev/config.yamlundervariables:, thenzdev down -v(removes DB volume so MariaDB reinitializes with new credentials) andzdev start. - Change the internal HTTP port by overriding
PORTin.zdev/config.yamlvariables:(defaults to80). Traefik terminates HTTPS externally, so this only affects the Symfony dev server inside the container. - Enable OpenSearch by flipping
SHOPWARE_ES_ENABLED/SHOPWARE_ES_INDEXING_ENABLEDto1, adding anopensearchservice to.zdev/config.yaml, and settingOPENSEARCH_URL=http://opensearch:9200. Then runzdev console es:indexto build the indexes. - After editing Twig templates under
src/Resources/views/orcustom/plugins/*/src/Resources/views/, no rebuild is needed — just refresh. - After editing storefront SCSS, run
zdev console theme:compile. - After editing storefront JS, run
zdev shopware-cli project storefront-build(orstorefront-watchfor HMR). - After editing admin JS/Vue, run
zdev shopware-cli project admin-build(oradmin-watchfor HMR). - To regenerate demo data with different counts:
zdev exec app bash -c "APP_ENV=prod php bin/console framework:demodata --products=100 --orders=50 --reset-defaults". - Any other
.zdev/config.yamlchange:zdev updatediffs the config against running containers and recreates only what changed.
This shouldn't happen with this template — SYMFONY_TRUSTED_PROXIES=private_ranges is set in .zdev/config.yaml and APP_URL is set to the HTTPS zdev URL. If you forked the template and dropped either, restore them: Traefik terminates HTTPS and forwards HTTP to Symfony, so without SYMFONY_TRUSTED_PROXIES Shopware generates http:// URLs inside the HTTPS page and the browser blocks the cookies / forms.
The boot step 30-assets.sh rebuilds automatically when its marker is absent, so zdev restart should be enough after a zdev down -v cleared the volume. To rebuild manually at any time:
zdev build # = shopware-cli project ci --with-dev-dependenciesExpected on a fresh install — the message appears until you run zdev console plugin:refresh. The template leaves the plugin list empty, so there are no actual incompatibilities.
zdev restart preserves the container. For env, image, command, or volume changes in .zdev/config.yaml, run zdev update — it diffs and recreates only what changed. Code changes (via bind mount / Mutagen) don't need any restart.
The image is published to GitHub Container Registry and should pull without authentication. If Docker reports an auth or not-found error, make sure your Docker daemon can reach ghcr.io (check proxy/VPN settings) and that you're not rate-limited. As a fallback, swap the image in .zdev/config.yaml for a public equivalent (e.g. php:8.4-cli-alpine plus manual extension install).
- zdev installed
- Docker Desktop running
- Network access to
ghcr.ioto pull theghcr.io/scalecommerce/docker-php-cli:8.4.20image (see ScaleCommerce/docker-php-cli)
- Shopware 6 developer documentation: https://developer.shopware.com/docs/
- Shopware installation guide: https://developer.shopware.com/docs/guides/installation/
- Shopware production repo (what we scaffold via
composer create-project): https://github.com/shopware/production - Shopware core repo: https://github.com/shopware/shopware
- Shopware CLI (useful for packaging extensions): https://github.com/shopware/shopware-cli
- zdev documentation: https://github.com/0ploy/zdev
- Base PHP image: https://github.com/ScaleCommerce/docker-php-cli