Shopware 6 Produktions- und Staging-Umgebung (2/2)

Vollständiger Leitfaden für Setup und automatisches Deployment

Inhaltsverzeichnis

Dieser Leitfaden ist in zwei Teile gegliedert:

  • Teil 1: Server-Umgebung Setup (Produktion & Staging) - Grundlegende Infrastruktur
  • Teil 2: Entwicklungsumgebung und automatisches Deployment - CI/CD-Pipeline

Teil 2: Entwicklungsumgebung und automatisches Deployment

In Teil 1 wurde die Shopware6-Produktions- und Staging-Umgebung aufgebaut. Teil 2 erklärt vom lokalen Entwicklungsumgebungs-Setup bis zur Implementierung des automatischen Deployments. Die nachstehenden Schritte zeigen, wie eine effiziente Entwicklungsumgebung aufgebaut und automatisches Deployment mit GitHub Actions realisiert wird.

1. Lokale Entwicklungsumgebung vorbereiten

Docker überprüfen

Überprüfen, ob Docker Desktop oder Docker installiert ist:

docker --version
docker-compose --version

Projektverzeichnis erstellen

mkdir shopware-project
cd shopware-project

2. Shopware6 Setup mit Dockware

Initiale docker-compose.yml erstellen

nano docker-compose.yml

Folgenden Inhalt eingeben:

services:
  shopware:
    image: dockware/dev:latest # Gleiche Version wie Produktionsumgebung spezifizieren
    container_name: shopware # Container-Name
    ports:
      - "80:80"
      - "3306:3306"
      - "22:22"
      - "8888:8888"
      - "9999:9999"
      - "9998:9998"
    networks:
      - web
    environment:
      - XDEBUG_ENABLED=1
      - PHP_VERSION=8.3 # Gleiche Version wie Produktionsumgebung
      - NODE_VERSION=22 # Gleiche Version wie Produktionsumgebung

networks:
  web:
    external: false

Shopware6 Initial-Installation

# Container starten
docker compose up -d

# Container-Start überprüfen
docker ps

# Shopware-Dateien auf Host kopieren
mkdir -p ./src
docker cp shopware:/var/www/html/. ./src

# Berechtigungen setzen
docker exec -it shopware bash -c 'sudo chown www-data:www-data /var/www/html -R'

# Container einmal stoppen
docker compose down

docker-compose.yml aktualisieren

Durch folgenden Inhalt ersetzen:

services:
  shopware:
    image: dockware/dev:latest
    container_name: shopware
    volumes:
      - "./src:/var/www/html/"
      # Ausschluss-Volumes (im Container verwaltet)
      - "/var/www/html/.git/"
      - "/var/www/html/public/build"
      - "/var/www/html/var/cache"
      - "/var/www/html/vendor"
      - "db_volume:/var/lib/mysql"
    ports:
      - "80:80"
      - "3306:3306"
      - "22:22"
      - "8888:8888"
      - "9999:9999"
      - "9998:9998"
    networks:
      - web
    environment:
      - XDEBUG_ENABLED=1
      - PHP_VERSION=8.3
      - NODE_VERSION=22

volumes:
  db_volume:
    driver: local

networks:
  web:
    external: false

Entwicklungsumgebung starten und überprüfen

# Container neu starten
docker compose up -d

# Im Browser überprüfen
echo "Shop: http://localhost"
echo "Admin: http://localhost/admin (admin/shopware)"

3. Git-Verwaltungskonfiguration für Projekt

.gitignore-Datei erstellen

Folgenden Inhalt eingeben:

# IDE
/.idea
/.vscode

# Dependencies
/vendor/
/node_modules/

# Environment files
.env.local
.env.local.php
.env.*.local

# Generated/Compiled Assets
/public/bundles/
/public/css/
/public/fonts/
/public/js/
/public/theme/
/public/asset-manifest.json

# Cache & Temporary Files
/public/thumbnail/*
/public/sitemap/*
/public/media/cache/
/public/media/temp/
/var/cache/
/var/log/
/var/session/
/files/cache/
/files/temp/
/files/media_tmp/

# Security & Installation
/auth.json
/install.lock
/config/jwt/

# Shopware export files
/files/export/

# Docker
docker-compose.override.yml

# Keep important directories
!/var/.htaccess
!/files/.htaccess

# Custom plugins managed by Composer
/custom/plugins/*
!/custom/plugins/.gitkeep

4. Notwendige Abhängigkeiten hinzufügen

Deployer-bezogene Pakete im Container hinzufügen:

# In Container eintreten
docker exec -it shopware bash

# Deployer-bezogene installieren
composer require deployer/deployer shopware/deployment-helper

# Container verlassen
exit

5. Deployer-Konfiguration

deploy.php-Datei erstellen

nano deploy.php

Folgenden Inhalt eingeben (Server-IP-Adresse entsprechend ändern):

<?php

namespace Deployer;

require_once 'recipe/common.php';
require_once 'contrib/cachetool.php';

set('bin/console', '{{bin/php}} {{release_or_current_path}}/bin/console');
set('cachetool', '/run/php/php8.3-fpm.sock');
set('application', 'Shopware 6');
set('allow_anonymous_stats', false);
set('default_timeout', 3600);

// Staging-Umgebung-Konfiguration
host('staging')
    ->setHostname('YOUR_SERVER_IP') // Auf Server-IP-Adresse ändern
    ->setLabels([
        'type' => 'web',
        'env'  => 'staging',
    ])
    ->setRemoteUser('www-data')
    ->set('deploy_path', '/var/www/shopware-staging')
    ->set('http_user', 'www-data')
    ->set('writable_mode', 'chmod')
    ->set('keep_releases', 3);

// Produktionsumgebung-Konfiguration
host('production')
    ->setHostname('YOUR_SERVER_IP') // Auf Server-IP-Adresse ändern
    ->setLabels([
        'type' => 'web',
        'env'  => 'production',
    ])
    ->setRemoteUser('www-data')
    ->set('deploy_path', '/var/www/shopware-prod')
    ->set('http_user', 'www-data')
    ->set('writable_mode', 'chmod')
    ->set('keep_releases', 3);

// Geteilte Dateien
set('shared_files', [
    '.env.local',
    'install.lock',
    'public/.htaccess',
    'public/.user.ini',
]);

// Geteilte Verzeichnisse
set('shared_dirs', [
    'config/jwt',
    'files',
    'var/log',
    'public/media',
    'public/thumbnail',
    'public/sitemap',
    'custom/plugins',
    'custom/apps',
]);

// Schreibbare Verzeichnisse
set('writable_dirs', [
    'config/jwt',
    'files',
    'public/bundles',
    'public/css',
    'public/fonts',
    'public/js',
    'public/media',
    'public/sitemap',
    'public/theme',
    'public/thumbnail',
    'var',
]);

// Shopware-spezifische Tasks
task('sw:deployment:helper', static function() {
    run('cd {{release_path}} && vendor/bin/shopware-deployment-helper run');
});

task('sw:assets:install', static function() {
    run('cd {{release_path}} && {{bin/console}} assets:install');
});

task('sw:touch_install_lock', static function () {
    run('cd {{release_path}} && touch install.lock');
});

task('sw:health_checks', static function () {
    run('cd {{release_path}} && bin/console system:check --context=pre_rollout');
});

// Upload-Task
task('deploy:update_code')->setCallback(static function () {
    upload('.', '{{release_path}}', [
        'options' => [
            '--exclude=.git',
            '--exclude=deploy.php',
            '--exclude=node_modules',
            '--exclude=.github',
        ],
    ]);
});

// Haupt-Deployment-Task
desc('Deploys your project');
task('deploy', [
    'deploy:prepare',
    'deploy:clear_paths',
    'sw:deployment:helper',
    'sw:assets:install',
    'sw:touch_install_lock',
    'deploy:publish',
]);

// Hooks
after('deploy:failed', 'deploy:unlock');
after('deploy:symlink', 'cachetool:clear:opcache');
after('sw:touch_install_lock', function () {
    if (get('labels')['env'] === 'production') {
        invoke('sw:health_checks');
    }
});

6. SSH-Schlüssel generieren und konfigurieren

SSH-Schlüssel lokal generieren

# SSH-Schlüssel generieren
ssh-keygen -t ed25519 -f ~/.ssh/shopware_deploy

# Öffentlichen Schlüssel kopieren
cat ~/.ssh/shopware_deploy.pub

Öffentlichen Schlüssel auf Server hinzufügen

Auf Server folgendes ausführen:

# Öffentlichen Schlüssel zu authorized_keys hinzufügen (YOUR_SSH_PUBLIC_KEY_CONTENT ist der oben kopierte Inhalt)
sudo -u www-data tee -a /var/www/.ssh/authorized_keys << 'EOF'
YOUR_SSH_PUBLIC_KEY_CONTENT_HERE
EOF

# Berechtigungen setzen
sudo chmod 600 /var/www/.ssh/authorized_keys

SSH-Verbindungstest

# Verbindungstest von lokal
ssh -i ~/.ssh/shopware_deploy www-data@YOUR_SERVER_IP

7. GitHub Actions Workflow-Konfiguration

Branch-Strategie

  • staging: Automatisches Deployment zur Staging-Umgebung
  • main: Automatisches Deployment zur Produktionsumgebung (vorsichtig mergen)

.github/workflows-Verzeichnis erstellen

mkdir -p .github/workflows

Workflow für Staging-Umgebung

nano .github/workflows/deploy-staging.yml

Folgenden Inhalt eingeben:

name: Deploy to Staging
on:
  push:
    branches:
      - staging

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: "8.3"

      - name: Install Shopware CLI
        uses: shopware/shopware-cli-action@v1

      - name: Build
        run: shopware-cli project ci .

      - name: Deploy
        uses: deployphp/action@v1
        with:
          dep: deploy staging
          private-key: ${{ secrets.SSH_PRIVATE_KEY }}

Erklärung der GitHub Actions-Schritte

Rolle jedes Schritts:

  • Checkout: Repository-Code auf Runner herunterladen
  • Setup PHP: Gleiche PHP 8.3 wie Produktionsumgebung vorbereiten
  • Install Shopware CLI: Shopware6-spezifisches Build-Tool installieren
  • Build: Asset-Build und -Optimierung (shopware-cli project ci-Befehl)
  • Deploy: Deployment auf Server mit Deployer

Workflow für Produktionsumgebung

nano .github/workflows/deploy-production.yml

Folgenden Inhalt eingeben:

name: Deploy to Production
on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: "8.3"

      - name: Install Shopware CLI
        uses: shopware/shopware-cli-action@v1

      - name: Build
        run: shopware-cli project ci .

      - name: Deploy
        uses: deployphp/action@v1
        with:
          dep: deploy production
          private-key: ${{ secrets.SSH_PRIVATE_KEY }}

8. GitHub-Repository erstellen und konfigurieren

Repository initialisieren

# Git-Repository initialisieren
git init

# .gitkeep-Datei erstellen
touch custom/plugins/.gitkeep

# Erster Commit
git add .
git commit -m "Initial commit"

# Nach Erstellung des GitHub-Repositorys Remote hinzufügen
git remote add origin https://github.com/your-username/your-shopware-project.git
git branch -M main
git push -u origin main

# staging-Branch erstellen
git switch -c staging
git push -u origin staging

GitHub Secrets konfigurieren

Privaten Schlüssel kopieren
# Privaten Schlüssel lokal kopieren
cat ~/.ssh/shopware_deploy
Secret in GitHub-Repository-Einstellungen hinzufügen
  1. Repository-Seite Settings > Secrets and variables > Actions öffnen
  2. New repository secret klicken
  3. Wie folgt hinzufügen:
  • Name: SSH_PRIVATE_KEY
  • Value: Kopierten privaten Schlüssel einfügen (von -----BEGIN OPENSSH PRIVATE KEY----- bis -----END OPENSSH PRIVATE KEY-----)

9. Benutzerdefinierte Plugin-Verwaltung

Vorteile der VCS-Verwaltung

Durch Verwaltung benutzerdefinierter Plugins in separaten Repositories:

  • Unabhängige Entwicklung: Plugin und Hauptprojekt unabhängig
  • Versionsverwaltung: Individuelle Versionierung von Plugins
  • Wiederverwendbarkeit: Gleiche Plugins in anderen Projekten verwendbar
  • Team-Entwicklung: Einfache Zusammenarbeit mit Plugin-Entwicklungsteam

Bei Verwaltung benutzerdefinierter Plugins in separaten Repositories:

composer.json aktualisieren

Folgendes zu composer.json hinzufügen:

{
  "require": {
    "your-org/your-plugin": "dev-develop"
  },
  "repositories": [
    {
      "type": "vcs",
      "url": "https://github.com/your-org/your-plugin"
    }
  ]
}

Umgebungs-spezifische Konfigurationsbeispiele

Staging-Umgebung (für Entwicklung und Test):

"your-org/your-plugin": "dev-develop"

Produktionsumgebung (nur stabile Versionen):

"your-org/your-plugin": "^1.0.0"

GitHub-Zugriffstoken konfigurieren

Für Zugriff auf GitHub-Repositories ist ein Zugriffstoken erforderlich. Token auf GitHub generieren und im Shopware-Container konfigurieren.

# Im Container ausführen
docker exec -it shopware bash
composer config --global github-oauth.github.com YOUR_GITHUB_TOKEN
exit

Server-Konfiguration (PHP-FPM-Einstellungen)

Folgende Konfiguration zu /etc/php/8.3/fpm/pool.d/www.conf hinzufügen. Ohne diese Konfiguration treten bei Shopware-Updates Fehler auf:

env[PATH] = /usr/local/bin:/usr/bin:/bin
env[GIT_EXEC_PATH] = /usr/bin
env[COMPOSER_AUTH] = '{"github-oauth":{"github.com":"YOUR_ACTUAL_TOKEN_HERE"}}'

Nach der Konfiguration PHP-FPM neu starten:

sudo systemctl restart php8.3-fpm

10. Erstes Deployment ausführen

Deployment-Flow überprüfen

Erstes Deployment-Ablauf:

  1. Staging: Push zu staging-Branch und Funktionsprüfung
  2. Produktionsvorbereitung: Nach Bestätigung in staging zu main-Branch mergen
  3. Produktions-Deployment: Push zu main-Branch für automatisches Deployment

Deployment zur Staging-Umgebung

# Zu staging-Branch wechseln
git switch staging

# Änderungen pushen (GitHub Actions wird automatisch ausgeführt)
git push origin staging

Staging-Modus aktivieren

Nach Abschluss des Deployments auf Server folgendes ausführen:

# Zu Staging-Verzeichnis wechseln
cd /var/www/shopware-staging/current

# Staging-Modus aktivieren
bin/console system:setup:staging

# Cache leeren
bin/console cache:clear

exit

Effekt des Staging-Modus:

  • Verhindert Suchmaschinen-Indexierung
  • Fügt “Staging”-Anzeige zum Admin-Panel hinzu
  • Klare Unterscheidung von Produktionsumgebung

Deployment zur Produktionsumgebung

# Zu main-Branch wechseln
git switch main

# Änderungen von staging mergen
git merge staging

# Pushen (GitHub Actions wird automatisch ausgeführt)
git push origin main

Zusammenfassung

Vorteile des aufgebauten Systems

Durch diese Schritte kann ein Shopware6-Produktions- und Staging-Umgebungs- sowie automatisches Deployment-System mit folgenden Vorteilen aufgebaut werden:

  1. Sicherheit: Firewall-Konfiguration, SSH-Schlüssel-Authentifizierung, Umgebungstrennung
  2. Performance: PHP-FPM, Caddy-Optimierung, OPcache-Nutzung
  3. Betriebsfähigkeit: Zero-Downtime-Deployment mit Deployer
  4. Wartbarkeit: Umgebungs-spezifische Konfiguration, Versionsverwaltung mit Git

Ich hoffe, dieser Artikel hilft beim Aufbau der Shopware6-Produktionsumgebung. Falls es Verbesserungspunkte im Artikel gibt oder Sie Fragen oder Feedback haben, sprechen Sie mich gerne an!


Referenzen