Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Docker und MySQL für React-Projekte einrichten

Docker und MySQL einrichten

~14 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026

Unsere Bewertungen leben bisher nur im React-State – nach jedem Neuladen sind sie weg. In diesem und dem nächsten Kapitel bauen wir einen eigenen, kleinen Server samt Datenbank, damit Bewertungen wirklich dauerhaft gespeichert werden. Der erste Schritt: Docker und eine MySQL-Datenbank.

Was ist Docker, ganz genau?

Eine Datenbank wie MySQL ist eigentlich ein eigenständiges Programm, das Sie normalerweise aufwändig auf Ihrem Computer installieren, konfigurieren und pflegen müssten – mit Versionskonflikten, Betriebssystem-Unterschieden und viel manueller Einrichtung. Docker löst dieses Problem, indem es Programme in "Containern" verpackt: fertig konfigurierte, isolierte Mini-Umgebungen, die auf jedem Computer identisch laufen, egal ob Windows, Mac oder Linux.

Docker-BegriffVergleich
Image – die "Bauanleitung"/das "Rezept" für einen Container, z. B. "MySQL Version 8"vergleichbar mit einer .dmg/.exe-Installationsdatei, nur reproduzierbar und identisch für jeden
Container – eine LAUFENDE Instanz eines Imagesvergleichbar mit einem laufenden Programm/Prozess – Sie können mehrere Container aus demselben Image starten
docker-compose.yml – eine Konfigurationsdatei, die mehrere zusammengehörige Container beschreibtvergleichbar mit einer package.json, nur für ganze Programme/Dienste statt npm-Pakete

docker-compose.yml anlegen

Legen Sie im Hauptordner (auf derselben Ebene wie package.json, NICHT in src/) die Datei docker-compose.yml an:

docker-compose.yml
services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: geheimespasswort
      MYSQL_DATABASE: produktkatalog
    ports:
      - '3306:3306'
    volumes:
      - mysql-daten:/var/lib/mysql

volumes:
  mysql-daten:

Zeile für Zeile: image: mysql:8.0 lädt automatisch das offizielle, fertig konfigurierte MySQL-Image von Docker Hub (dem "App Store" für Container-Images) herunter. environment setzt Umgebungsvariablen, die das MySQL-Image selbst auswertet, um beim allerersten Start automatisch ein Root-Passwort und eine leere Datenbank namens produktkatalog anzulegen. ports: '3306:3306' verbindet den Port 3306 IM Container mit Port 3306 AUF Ihrem Computer, damit Programme außerhalb des Containers (unser gleich folgender Node-Server) sich verbinden können. volumes sorgt dafür, dass die Datenbank-Dateien auch nach einem docker compose down erhalten bleiben, statt mit dem Container gelöscht zu werden.

MySQL starten

docker compose up -d

-d ("detached") startet die Container im Hintergrund, statt Ihr Terminal zu blockieren. Prüfen Sie, ob es läuft:

docker compose ps

Sie sollten einen Eintrag mit Status "running" oder "Up" sehen. Zum Beenden später: docker compose down (die Datenbank-DATEN bleiben dank volumes erhalten, nur der laufende Container wird gestoppt).

server/: den Grundstein für unseren Node-Server legen

Unser eigener Server lebt in einem eigenen Ordner server/, komplett getrennt von src/ (das ist React-Code, der im BROWSER läuft) – der Server-Code läuft dagegen direkt mit Node.js, ohne Browser. Legen Sie server/package.json an:

server/package.json
{
  "name": "produktkatalog-server",
  "type": "module",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.19.0",
    "mysql2": "^3.9.0",
    "cors": "^2.8.5"
  }
}

"type": "module" aktiviert moderne import/export-Syntax statt des älteren require() – dieselbe Syntax, die Sie im gesamten src/-Ordner schon verwenden. Installieren Sie die drei Pakete:

cd server
npm install
cd ..

express ist das gängigste Web-Server-Framework für Node.js (vergleichbar mit Symfony/Laravel-Routing in der PHP-Welt, nur deutlich minimalistischer). mysql2 ist der Datenbanktreiber, mit dem wir uns aus Node.js heraus mit unserem gerade gestarteten MySQL-Container verbinden. cors erlaubt unserer React-App (läuft auf localhost:5173), Anfragen an unseren Server (läuft auf einem anderen Port) zu stellen – ohne cors blockiert der Browser das standardmäßig aus Sicherheitsgründen.

server/db.js: die Datenbankverbindung

server/db.js
import mysql from 'mysql2/promise';

export const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'geheimespasswort',
  database: 'produktkatalog',
});

mysql2/promise statt mysql2 ist wichtig – die "promise"-Variante unterstützt async/await aus Kapitel 22, statt nur Callback-Funktionen. Ein "Pool" verwaltet automatisch mehrere wiederverwendbare Datenbankverbindungen im Hintergrund, statt für jede Anfrage eine neue Verbindung aufzubauen und wieder zu schließen – deutlich performanter.

server/server.js: das Grundgerüst

server/server.js
import express from 'express';
import cors from 'cors';
import { pool } from './db.js';

const app = express();
app.use(cors());
app.use(express.json());

app.get('/api/health', async (req, res) => {
  const [rows] = await pool.query('SELECT 1 AS ok');
  res.json({ status: 'ok', datenbankVerbunden: rows[0].ok === 1 });
});

app.listen(4000, () => {
  console.log('Server läuft auf http://localhost:4000');
});

app.use(express.json()) sorgt dafür, dass Express eingehende JSON-Anfragen automatisch in req.body umwandelt (das brauchen wir im nächsten Kapitel für neue Bewertungen). Starten Sie den Server und testen Sie den Gesundheitscheck:

cd server
node server.js

Öffnen Sie in einem zweiten Terminal (oder Browser-Tab) http://localhost:4000/api/health – Sie sollten {{"status":"ok","datenbankVerbunden":true}} sehen. Das bestätigt: Node-Server UND MySQL-Verbindung funktionieren beide.

Ziel-Projektstruktur (Erinnerung aus Kapitel 3) – server/ nimmt jetzt Form an

produktkatalog-web/
├── index.html
├── package.json
├── vite.config.js
├── docker-compose.yml            (MySQL-Container für Bewertungen)
├── server/                       (eigener Node/Express-Server)
│   ├── package.json
│   ├── server.js
│   └── db.js
└── src/
    ├── main.jsx
    ├── App.jsx                   (Routing)
    ├── index.css
    ├── api/
    │   ├── magentoApi.js         (Magento-REST-API: Produkte)
    │   └── reviewsApi.js         (eigener Server: Bewertungen)
    ├── context/
    │   └── AuthContext.jsx       (einfacher Login-Zustand)
    ├── components/
    │   ├── ProductCard.jsx
    │   └── ProtectedRoute.jsx
    ├── hooks/
    │   └── useDocumentTitle.js   (Custom Hook)
    └── pages/
        ├── ProductListPage.jsx
        ├── ProductDetailPage.jsx
        ├── ReviewsPage.jsx       (verschachtelte Route)
        ├── LoginPage.jsx
        └── AccountPage.jsx       (geschützte Route)

Achtung: Ein echtes Passwort gehört NIEMALS direkt in den Code, wie wir es hier zur Vereinfachung tun – in einem echten Projekt würden Sie Zugangsdaten in einer .env-Datei speichern (die NICHT ins Git-Repository eingecheckt wird) und über das Paket dotenv laden. Für dieses lokale Lern-Setup ist das feste Passwort im Code eine bewusste Vereinfachung.