Shop­ware develop­ment Setup: docker, nginx, php-fpm 7.1 und mysql

Update 29.07.2018

Wir haben die docker-compose.yml auf github https://github.com/pmphillip/docker-shopware-setup aktualisiert und eine .env Datei hinzugefügt. In der .env Datei werden die wichtigsten Umgebungsvariablen definiert. Wir werden den Beitrag beizeiten komplett aktualisieren, bis dahin kontaktiert uns einfach wenn ihr Fragen zum Setup habt. Folgende Änderungen haben wir an der docker-compose.yml vorgenommen:

  • link durch network ersetzt
  • php und nginx laufen nun in einem container
  • php auf 7.1 upgedatet
  • Umgebungsvariablen eingeführt
  • phpmyadmin container hinzugefügt, localhost:8083 verfügbar
  • shopware aktualisiert auf 5.4

docker Setup für Shopware Entwicklung

In diesem Beitrag möchten wir euch ein einfaches docker Setup für die Shopware Entwicklung vorstellen. Falls ihr selber programmiert und noch keine Erfahrungen mit docker aufweisen könnt, kann ich euch nur empfehlen, das nachzuholen. Es lohnt sich! Wir setzen in unseren Projekten häufig unterschiedliche Technologien ein – und wir wissen, wie nervig es sein kann, wenn ein neuer Mitarbeiter anfängt und den ganzen Tag nichts anderes macht, als seinen Laptop zu konfigurieren und die entsprechenden Technologien für sein spezifisches Projekt zu installieren. Docker löst dieses Problem und ist daher für uns ein ganz zentrales Tool in der Entwicklung geworden.

Wenn wir eCommerce Projekte umsetzen, kommt häufig Shopware zum Einsatz. Als Webserver setzen wir auf nginx, obwohl Shopware offiziell nur apache unterstützt. Bisher haben wir aber den Eindruck, dass die Shops mit nginx schneller laufen als mit apache. Falls ihr andere Erfahrungen gemacht habt, lasst es uns gerne in den Kommentaren wissen. Ich bin auf euer Setup gespannt und wir lernen immer gerne Neues dazu! 🙂 Die aktuellste PHP Version können wir momentan noch nicht nutzen und müssen uns mit 7.0 begnügen. Denn Shopware und diverse Plugin Anbieter verschlüsseln den Code mit IonCube. Letzterer unterstützt bisher nur PHP 7.0. Sei’s drum. Legen wir los.

Wenn man mehrere Container verwalten möchte, bietet es sich an, docker-compose zu verwenden. Um die container zu konfigurieren, legen wir eine Datei mit dem Namen docker-compose.yml an. Die Datei wird von docker-compose eingelesen, sofern das Kommando im gleichen Verzeichnis ausgeführt wird. Legen wir zuerst einen container für nginx an.

web:
    image: nginx
    ports:
        - "8080:80"

Nach einem docker-compose up

sollten wir im browser unter localhost:8080 folgendes sehen.

Screenshot nginx Willkommensnachricht

PHP Container hinzufügen

Wunderbar. Nun fügen wir den PHP container hinzu. Dafür nutzen wir ein docker image, das wir erstellt haben. Wenn euch das Dockerfile interessiert, findet ihr das ganze Setup auch auf github. Im Wesentlichen geht unser image von dem offiziellen php image aus und installiert Komponenten nach wie z.B. IonCube. Um zu überprüfen, ob php funktioniert, legen wir eine index.php an, die letztlich nur die aktuelle Konfiguration ausspuckt.

Screenshot: PHP Container hinzufügen

Unsere docker-compsoe.yml wird auch entsprechend angepasst und sieht nun so aus:

web:
    image: nginx:latest
    ports:
        - "8080:80"
    volumes:
        - ./public:/var/www/html
        - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    links:
        - php-7.0
php-7.0:
    image: php
    volumes:
        - ./public:/var/www/html

Mit dem volume Befehl können wir docker sagen, dass er bestimmte Ordner oder auch Dateien in den container mounten soll. Wir haben für den nginx service zwei volumes angelegt. Zum einen wird der lokale public Ordner nach /var/www/html gemountet und zum anderen wollen wir die default.conf von nginx überschreiben mit dem Ziel, die php Anfragen an unseren php container weiterzuleiten. Der link Befehl macht es möglich, von einem service (nginx) auf einen anderen zuzugreifen. (php)

server {
    listen 80;
    server_name localhost;
    root /var/www/html;
    gzip on;
    gzip_buffers 32 4k; #default
    gzip_comp_level 1; #default
    gzip_min_length 20; #default
    gzip_http_version 1.1; #default
    gzip_proxied off; #default
    if ($time_iso8601 ~ "^(d{4})-(d{2})-(d{2})T(d{2})") {
        set $year $1;
        set $month $2;
        set $day $3;
        set $hour $4;
    }
    access_log /var/log/nginx/access.log main;
    location / {     
        index index.html index.php shopware.php;
        rewrite shopware.dll /shopware.php;
        rewrite files/documents/.* /engine last;
        #rewrite images/ayww/(.*) /images/banner/$1 last;
        rewrite backend/media/(.*) /media/$1 last;
        if (!-e $request_filename){
            rewrite . /shopware.php last;
        }
        location ~ .(jpe?g|png|gif|css|js)$ {
            rewrite backend/media/(.*) /media/$1 last;
            expires 1M;
        }
    }
    location ~ [^/].php(/|$) {
            fastcgi_split_path_info ^(.+?.php)(/.*)$;
            if (!-f $document_root$fastcgi_script_name) {
                return 404;
            }
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
            fastcgi_pass php-7.0:9000;
    }
}

So könnte eine einfache Konfiguration für nginx mit Shopware aussehen. Der Inhalt soll uns nicht weiter interessieren, außer vielleicht Zeile 52: fastcgi_pass php-7.0:9000. Mit der Anweisung sagen wir nginx, dass er doch bitte alle php Anfragen an den service php-7.0 auf Port 9000 weiterleiten soll. Um das nachzuvollziehen, stoppen wir zuerst alle container mit docker-compose down und fahren sie dann wieder hoch (docker-compose up). Nun sollten wir im Idealfall folgendes sehen:

Screenshot PHP Datenbank Installation

Datenbank installieren

Fein. Was fehlt noch um Shopware zu installieren? Richtig. Eine Datenbank. Wir nutzen hier das offizielle mysql docker image. Also wieder ran an die docker-compose.yml.

web:
    image: nginx:latest
    ports:
        - "8080:80"
    volumes:
        - ./public:/var/www/html
        - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    links:
        - php-7.0       
php-7.0:
    image: php
    volumes:
        - ./public:/var/www/html
    links:
        - mysql
mysql:
    image: mysql
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=db
      - MYSQL_USER=shopware
      - MYSQL_PASSWORD=shopware

Im Prinzip ist nicht viel neues dazu gekommen, außer dass wir den mysql service mit den wichtigsten environment Variablen vorkonfigurieren. Nun brauchen wir noch Shopware. Ladet euch dazu die neueste community Version herunter und entpackt alles in unseren public Ordner. Eure Ordnerstruktur sollte wie folgt aussehen.

Screenshot Shopware Ordnerstruktur

Ein letztes mal stoppen wir alle services mit docker-compose down. Überprüft mit docker ps ob wirklich alle services gestoppt wurden. Fahrt dann die services wieder hoch. Durchaus möglich, das es diesmal etwas länger dauert. Wechselt im Browser auf localhost:8080/recovery/install

Im besten Fall erscheint nun die Installationsroutine von Shopware.

Screenshot Installationsroutine Shopware

Klickt euch durch die Installationsroutine bis ihr aufgefordert werdet, die Datenbank zu konfigurieren.

Screenshot Datenbank Konfiguration Shopware

Gebt hier die Informationen aus der docker-compose.yml an.

Host: mysql

User: shopware

Passwort: shopware

Datenbank: db

Und damit sind wir fast am Ende. Wenn die Installation abgeschlossen ist, könnt ihr euch das frontend und backend angucken.

Fazit

Durch docker haben wir uns ein lokales Shopware Setup erzeugt, ohne libraries oder frameworks nativ auf unserem System zu installieren. Das ist viel Wert. Insbesondere, wenn man mal schnell die php oder mysql Version wechseln möchte. Die komplette Demo mit allen sourcen findet ihr hier https://github.com/pmphillip/docker-shopware-setup .

Ich habe bewusst alle Shopware sourcen mit eingecheckt, damit ihr es so einfach wie möglich habt, das Beispiel nachzuvollziehen. Das ist natürlich nicht gerade „best practice“, macht es aber in diesem Fall für alle einfacher. Des Weiteren kann man darüber streiten, ob man nginx und php als separate Container definiert. Darüber gibt es geteilte Meinungen: Die einen sagen, dass pro Container nur ein Prozess laufen darf. Andere wiederum meinen, dass dies eins der größten Missverständnisse bezüglich docker ist. Wie steht ihr dazu?

Über den Autor

Phillip Schulte

Scroll to Top