Shopware-Entwicklungsumgebung einrichten: VPS mit DDEV und Docker (Teil 1)

Serie: Professionelle Shopware-Entwicklungsumgebung
Dies ist Teil 1 der Serie. In den nächsten Teilen zeige ich dir, wie du deine lokale IDE per SSH-Tunnel anbindest, deine Versionskontrolle aufsetzt und deine Code-Qualität automatisierst.

Wer Shopware-Plugins entwickeln will, braucht eine saubere Entwicklungsumgebung. Keine zusammengeklickte XAMPP-Installation, kein Gefrickel mit lokalen PHP-Versionen — sondern eine Umgebung, die dem Live-System so nah wie möglich kommt. In dieser Anleitung zeige ich dir Schritt für Schritt, wie du mit DDEV und Docker eine professionelle Shopware-Entwicklungsumgebung auf einem eigenen Server aufsetzt.

Warum ein eigener Server statt lokaler Installation?

Klar, du kannst Shopware direkt auf deinem Rechner installieren. Aber ein eigener VPS hat entscheidende Vorteile:

  • Identisch zum Produktivsystem: Dein Entwicklungsserver läuft auf dem gleichen Betriebssystem, den gleichen Diensten und der gleichen Architektur wie dein Live-Shop. Keine „Bei mir funktioniert es“-Momente mehr.
  • Keine Konflikte mit dem lokalen Setup: Dein Arbeitsrechner bleibt sauber. Keine kollidierenden PHP-Versionen, keine Datenbank-Reste von gestern, kein kaputter Docker-Desktop nach einem Windows-Update.
  • Von überall erreichbar: Ob im Büro, im Home-Office oder unterwegs — deine Entwicklungsumgebung ist per SSH immer verfügbar. Kein Laptop nötig, auf dem alles läuft.

Noch wichtiger: Du kannst eine Kopie deines Live-Shops in die Entwicklungsumgebung laden. Das bedeutet, du testest dein Plugin mit echten Produkten, echten Kategorien und echten Konfigurationen — nicht mit synthetischen Demodaten, die mit der Realität wenig zu tun haben.

Warum DDEV und nicht Dockware?

Für Docker-basierte Shopware-Umgebungen gibt es im Wesentlichen zwei Optionen: DDEV und Dockware. Ich setze auf DDEV — aus guten Gründen:

  • Isolierte Projekte: Jedes DDEV-Projekt bekommt seinen eigenen Container-Stack mit eigener Datenbank, eigenem Webserver und eigener PHP-Version. Bei Dockware teilen sich Projekte oft die gleiche Umgebung.
  • Multi-Version ohne Aufwand: Du willst Shopware 6.6 und 6.7 parallel testen? Mit DDEV legst du zwei Projekte an — fertig. Verschiedene PHP-Versionen, verschiedene MariaDB-Versionen, alles unabhängig.
  • Traefik-Routing: DDEV bringt einen Reverse-Proxy mit. Jedes Projekt ist automatisch unter einer eigenen Domain erreichbar — keine Port-Konflikte, kein manuelles Routing.
  • Aktive Community: DDEV ist ein Open-Source-Projekt mit breiter Community. Shopware, TYPO3, WordPress, Laravel — die Dokumentation deckt alles ab. Bei Problemen findest du schnell Hilfe.
  • Kein Vendor-Lock-in: DDEV ist herstellerunabhängig und funktioniert mit jedem PHP-Projekt. Dockware ist eng an Shopware gekoppelt. Wechselst du das Ökosystem, fängst du mit Dockware von vorn an.

Was du brauchst

Bevor wir loslegen, hier die Voraussetzungen. Du brauchst keinen High-End-Server — ein günstiger VPS mit ausreichend RAM reicht völlig.

Hardware

  • Server oder VPS mit mindestens 4 Kernen und 8 GB RAM
  • SSD-Speicher — mindestens 50 GB frei (Shopware + Datenbank brauchen Platz)
  • Stabile Internetverbindung zum Server

Software

  • Ubuntu 24.04 LTS als Betriebssystem
  • Docker (aktuelle Version)
  • DDEV (mindestens v1.23)
  • SSH-Zugang zum Server

Kenntnisse

Du solltest grundlegend mit der Linux-Kommandozeile umgehen können. PHP-Kenntnisse sind für die Plugin-Entwicklung natürlich Pflicht, aber für das Aufsetzen der Umgebung reichen Basics.

Schritt 1: Server vorbereiten

Verbinde dich per SSH mit deinem Server und bring das System auf den aktuellen Stand:

sudo apt update && sudo apt upgrade -y

Installiere die grundlegenden Pakete, die du später brauchst:

sudo apt install -y curl unzip ca-certificates gnupg lsb-release

Schritt 2: Docker installieren

Docker ist die Basis für alles Weitere. DDEV nutzt Container, um Shopware und die Datenbank zu betreiben.

# Docker GPG-Key hinzufügen
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Repository einrichten
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Docker installieren
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Deinen Benutzer zur Docker-Gruppe hinzufügen
sudo usermod -aG docker $USER

Wichtig: Nach dem letzten Befehl musst du dich ab- und wieder anmelden, damit die Gruppenänderung greift. Danach prüfst du die Installation:

docker --version
docker compose version

Schritt 3: DDEV installieren

DDEV ist ein Open-Source-Tool, das Docker-basierte Entwicklungsumgebungen extrem einfach macht. Statt Docker-Compose-Dateien von Hand zu schreiben, konfigurierst du dein Projekt mit ein paar Befehlen.

# DDEV installieren
curl -fsSL https://ddev.com/install.sh | bash

# Installation prüfen
ddev version

DDEV bringt automatisch einen Traefik-Reverse-Proxy mit. Der sorgt dafür, dass jedes Projekt über eine eigene Domain erreichbar ist — zum Beispiel https://dev-shopware.ddev.site. Keine Port-Konflikte, keine manuelle nginx-Konfiguration.

Schritt 4: Shopware-Projekt mit DDEV anlegen

Jetzt wird es konkret. Wir erstellen ein neues DDEV-Projekt für Shopware 6.

# Projektverzeichnis erstellen
mkdir -p /workspace/shopware/dev-shopware
cd /workspace/shopware/dev-shopware

# DDEV konfigurieren
ddev config \
  --project-name=dev-shopware \
  --project-type=shopware6 \
  --php-version=8.3 \
  --docroot=public \
  --database=mariadb:10.11 \
  --webserver-type=nginx-fpm

DDEV legt damit eine Konfigurationsdatei unter .ddev/config.yaml an. Die sieht so aus:

name: dev-shopware
type: shopware6
docroot: public
php_version: "8.3"
webserver_type: nginx-fpm
database:
  type: mariadb
  version: "10.11"
router_http_port: "80"
router_https_port: "443"

Starte die Umgebung:

ddev start

Beim ersten Start lädt DDEV die nötigen Docker-Images herunter. Das dauert je nach Internetverbindung ein paar Minuten. Danach läuft dein Shopware-Container und ist unter https://dev-shopware.ddev.site erreichbar.

Schritt 5: Shopware installieren

Im nächsten Schritt installierst du Shopware selbst. Hier gibt es zwei Wege:

Option A: Frische Installation mit Demodaten

Für ein sauberes Entwicklungs-Setup mit Beispieldaten:

# Shopware über Composer laden
ddev composer create shopware/production:6.6.* --no-interaction

# Shopware installieren
ddev exec bin/console system:install \
  --basic-setup \
  --create-database \
  --shop-locale=de-DE \
  --shop-currency=EUR

# Admin-Benutzer anlegen
ddev exec bin/console user:create admin \
  --admin \
  --firstName=Admin \
  --lastName=Admin \
  --email=admin@example.com \
  --password=shopware

# Cache leeren
ddev exec bin/console cache:clear

Option B: Live-Shop klonen (empfohlen)

Für die Plugin-Entwicklung ist es deutlich besser, mit echten Daten zu arbeiten. Dazu erstellst du ein Backup deines Live-Shops und importierst es in die Entwicklungsumgebung.

Auf dem Live-Server:

# Datenbank exportieren
mysqldump -u root shopware_live | gzip > ~/live_db.sql.gz

# Shop-Dateien sichern (ohne Cache und Logs)
tar czf ~/live_files.tar.gz \
  --exclude='var/cache' \
  --exclude='var/log' \
  --exclude='node_modules' \
  -C /pfad/zum/shop .

In der Entwicklungsumgebung:

# Backup herunterladen
scp user@live-server:~/live_db.sql.gz .
scp user@live-server:~/live_files.tar.gz .

# Dateien entpacken
tar xzf live_files.tar.gz -C /workspace/shopware/dev-shopware/

# Datenbank importieren
ddev import-db --file=live_db.sql.gz

Live-Klon isolieren — das ist Pflicht

Ein Live-Klon enthält echte Kundendaten, echte Payment-Konfigurationen und echte API-Schlüssel. Bevor du irgendetwas anderes tust, musst du den Klon vollständig vom Produktivsystem trennen. Hier ist die komplette Checkliste:

1. Domains anpassen

Dein Live-Shop hat vermutlich mehrere Domains konfiguriert — Shop-Domain, CDN-Domain, verschiedene Sprach-Domains. Die müssen alle auf die DDEV-Domain umgebogen werden, sonst versucht dein Dev-Klon Requests an die Live-Domains zu schicken:

ddev exec -s db mysql -udb -pdb db -e "
  SET FOREIGN_KEY_CHECKS=0;
  DELETE FROM sales_channel_domain
    WHERE url NOT LIKE '%headless%'
    AND url != 'http://dev-shopware.ddev.site:8080';
  SET FOREIGN_KEY_CHECKS=1;
  UPDATE sales_channel_domain
    SET url = 'http://dev-shopware.ddev.site:8080'
    WHERE url NOT LIKE '%headless%';
"

Das löscht alle Domain-Einträge ausser Headless-Channels und setzt die verbleibenden auf deine lokale DDEV-URL. Headless-Channels haben eigene Domains und stören in der Entwicklung nicht.

2. Shop-ID aktualisieren

Der Klon übernimmt App-Registrierungen vom Live-Shop. Der Fingerprint — also die Kombination aus Domain und Pfaden — passt nach dem Umzug nicht mehr. Im Admin siehst du dann die Meldung „Änderung der Shop-ID wird vorgeschlagen“. Das behebst du so:

ddev exec bin/console app:shop-id:change uninstall-apps

Die Strategie uninstall-apps deinstalliert alle registrierten Apps und aktualisiert die Shop-ID. Apps wie SwagAnalytics oder SwagPayPal sind im Dev-Klon ohnehin nicht nötig — im Gegenteil, sie würden stören.

3. Store-Verbindung trennen

Der Klon hat noch die Store-Credentials deines Live-Shops. Damit könnte die Dev-Umgebung ungewollt Lizenzen prüfen oder Daten an den Shopware-Store senden:

ddev exec -s db mysql -udb -pdb db -e "
  DELETE FROM system_config WHERE configuration_key IN
    ('core.store.shopSecret','core.store.licenseKey',
     'core.store.licenseHost','core.store.iapKey');
"

4. Mailer und Messenger deaktivieren

# Mailer auf Null setzen (keine echten Mails!)
ddev exec bin/console system:config:set core.mailerAgent null

# Messenger synchron schalten (keine Queue-Jobs im Hintergrund)
ddev exec bin/console system:config:set \
  messenger.default_transport_dsn sync://

5. Tracking und Consent deaktivieren

# Tracking-Plugins deaktivieren
ddev exec bin/console plugin:deactivate ComanConsentManager
ddev exec bin/console plugin:deactivate WbmTagManagerAnalytics

6. Cache leeren und Theme neu bauen

ddev exec bin/console cache:clear
ddev exec bin/console theme:compile

Achtung: Überspringe keinen dieser Schritte. Ein vergessener Mailer kann dazu führen, dass echte Kunden E-Mails von deiner Entwicklungsumgebung bekommen. Nicht bereinigte Store-Credentials können Lizenzprobleme auf dem Live-Shop auslösen. Das sind keine theoretischen Risiken — das passiert.

Schritt 6: Entwicklungs-Tools einrichten

Eine gute Entwicklungsumgebung ist mehr als nur ein laufender Shop. Du brauchst Werkzeuge, die dir die Arbeit erleichtern.

Adminer (Datenbank-Verwaltung)

DDEV hat Adminer als Add-on. Damit kannst du direkt im Browser auf die Datenbank zugreifen:

ddev get ddev/ddev-adminer
ddev restart

Adminer ist danach über den DDEV-Router erreichbar — ohne eigene Konfiguration.

Mailpit (E-Mail-Testing)

DDEV fängt automatisch alle E-Mails ab, die aus dem Container gesendet werden. Über Mailpit kannst du sie im Browser ansehen — praktisch, um zu prüfen ob Bestellbestätigungen oder Newsletter korrekt aussehen.

Xdebug (Debugging)

Für echtes Debugging — Breakpoints, Variablen inspizieren, Step-Through — aktivierst du Xdebug:

# Xdebug aktivieren
ddev xdebug on

# Nach dem Debugging wieder deaktivieren (Performance!)
ddev xdebug off

In deiner IDE (PhpStorm, VS Code) richtest du dann einen Listener für Port 9003 ein. DDEV kümmert sich um den Rest.

Schritt 7: Plugin-Entwicklung starten

Die Umgebung steht. Zeit für das eigentliche Ziel: dein erstes Shopware-Plugin.

Plugin-Struktur anlegen

Shopware-Plugins folgen einer festen Struktur. Hier ein Beispiel für ein Plugin namens [PluginName]:

# Plugin-Verzeichnis erstellen
mkdir -p custom/plugins/[PluginName]/src/Resources/config

Die Verzeichnisstruktur sieht so aus:

custom/plugins/[PluginName]/
├── composer.json
└── src/
    ├── [PluginName].php
    └── Resources/
        └── config/
            └── services.xml

composer.json

{
    "name": "[vendor]/[plugin-name]",
    "description": "Beispiel-Plugin für Shopware 6",
    "type": "shopware-platform-plugin",
    "license": "MIT",
    "version": "1.0.0",
    "autoload": {
        "psr-4": {
            "[Vendor]\\[PluginName]\\": "src/"
        }
    },
    "extra": {
        "shopware-plugin-class": "[Vendor]\\[PluginName]\\[PluginName]",
        "label": {
            "de-DE": "Beispiel Plugin",
            "en-GB": "Example Plugin"
        }
    },
    "require": {
        "shopware/core": "~6.6.0"
    }
}

Bootstrap-Klasse

<?php

declare(strict_types=1);

namespace [Vendor]\[PluginName];

use Shopware\Core\Framework\Plugin;

class [PluginName] extends Plugin
{
}

Plugin registrieren und aktivieren

# Plugin erkennen
ddev exec bin/console plugin:refresh

# Plugin installieren und aktivieren
ddev exec bin/console plugin:install --activate [PluginName]

# Cache leeren
ddev exec bin/console cache:clear

Dein Plugin taucht jetzt im Shopware-Admin unter Einstellungen → System → Plugins auf.

Schritt 8: Tägliche Arbeit — die wichtigsten Befehle

Im Alltag wirst du immer wieder dieselben Befehle brauchen. Hier die wichtigsten auf einen Blick:

AufgabeBefehl
Umgebung startenddev start
Umgebung stoppenddev stop
In den Container wechselnddev ssh
Cache leerenddev exec bin/console cache:clear
Plugin aktualisierenddev exec bin/console plugin:refresh
Theme neu kompilierenddev exec bin/console theme:compile
Logs ansehenddev exec tail -f var/log/dev.log
Xdebug an/ausddev xdebug on / ddev xdebug off

Schritt 9: Mehrere Shopware-Versionen parallel betreiben

Wenn du Plugins für verschiedene Shopware-Versionen unterstützen musst, legst du einfach mehrere DDEV-Projekte an:

# Shopware 6.6 Umgebung
mkdir -p /workspace/shopware/dev-66 && cd /workspace/shopware/dev-66
ddev config --project-name=dev-66 --project-type=shopware6 \
  --php-version=8.3 --docroot=public --database=mariadb:10.11

# Shopware 6.7 Umgebung
mkdir -p /workspace/shopware/dev-67 && cd /workspace/shopware/dev-67
ddev config --project-name=dev-67 --project-type=shopware6 \
  --php-version=8.3 --docroot=public --database=mariadb:10.11

Jede Umgebung läuft isoliert mit eigener Datenbank und eigener URL. Du kannst dein Plugin per Symlink in beide Umgebungen einbinden:

# Gemeinsames Plugin-Verzeichnis
mkdir -p /workspace/plugins/[PluginName]

# Symlinks in beide Projekte
ln -s /workspace/plugins/[PluginName] \
  /workspace/shopware/dev-66/custom/plugins/[PluginName]

ln -s /workspace/plugins/[PluginName] \
  /workspace/shopware/dev-67/custom/plugins/[PluginName]

So entwickelst du das Plugin einmal und testest es gleichzeitig gegen mehrere Shopware-Versionen.

Häufige Probleme und Lösungen

DDEV startet nicht

Meistens liegt es an belegten Ports. Prüfe, ob ein anderer Webserver läuft:

# Welcher Prozess belegt Port 80?
sudo lsof -i :80

# Apache stoppen, falls aktiv
sudo systemctl stop apache2

502 Bad Gateway nach dem Start

Der PHPContainer braucht manchmal einen Moment. Warte ein paar Sekunden und lade die Seite neu. Falls es bleibt:

ddev restart

Plugin wird nicht erkannt

Prüfe, ob die composer.json korrekt ist und der Namespace stimmt. Dann:

ddev exec bin/console plugin:refresh
ddev exec bin/console cache:clear

Änderungen werden nicht sichtbar

Shopware cached aggressiv. Stelle sicher, dass du im Entwicklungsmodus arbeitest:

# In der .env APP_ENV auf dev setzen
# APP_ENV=dev

ddev exec bin/console cache:clear

Wie geht es weiter?

Deine Entwicklungsumgebung steht. Du hast einen VPS mit Docker und DDEV, einen laufenden Shopware-Shop und ein erstes Plugin-Gerüst. In den nächsten Teilen dieser Serie geht es weiter:

Die gezeigten Code-Beispiele dienen zur Veranschaulichung. Nutzung auf eigene Verantwortung. Mehr dazu