Zum Inhalt springen

Docker für Webentwickler – Container-Setup auf macOS (2025)

· von

Docker revolutioniert die Webentwicklung auf macOS. Statt lokale Server-Installationen zu pflegen, packst du LAMP, LEMP oder Node.js-Umgebungen in portable Container. Einmal konfiguriert, laufen deine Entwicklungsumgebungen identisch auf jedem Rechner. Hier zeige ich praxiserprobte Docker-Setups für moderne Webentwicklung – von einfachen PHP-Projekten bis zu komplexen Microservices.

Kontext: Dieser Artikel erweitert mein macOS Dev-Setup um containerbasierte Entwicklung.

Docker für Webentwickler – Container-Setup auf macOS – Symbolbild

~10 Min. Lesezeit · Veröffentlicht am

Warum Docker für Webentwickler?

Traditionelles Setup vs. Docker

Ohne Docker (traditionell):

  • Apache/Nginx direkt auf macOS installiert
  • PHP via Homebrew, verschiedene Versionen konfliktieren
  • MySQL läuft permanent im Hintergrund
  • "Works on my machine" Probleme

Mit Docker:

  • Isolierte Container für jedes Projekt
  • Verschiedene PHP-Versionen parallel
  • Services nur bei Bedarf gestartet
  • Identische Umgebung für alle Entwickler

Docker-Vorteile für Mac-Developer

Docker Desktop Installation auf macOS

Installation via Homebrew

# Docker Desktop installieren
brew install --cask docker

# Alternativ: Manueller Download von docker.com
# Docker.dmg herunterladen und installieren

# Erste Schritte nach Installation
docker --version
docker-compose --version

# Docker Desktop starten (GUI-App)
open /Applications/Docker.app

Wichtige Docker Desktop Einstellungen für macOS:

  • Memory: Mindestens 4GB, optimal 8GB für Web-Development
  • CPUs: Minimum 2, besser 4 Kerne zuweisen
  • Disk Space: 64GB+ für Images und Container
  • File Sharing: Projektordner freigeben für Volume-Mounts

Docker System konfigurieren

# Docker-Daemon Einstellungen (optional)
# ~/.docker/daemon.json
{
  "builder": { "gc": { "defaultKeepStorage": "20GB" } },
  "experimental": false,
  "features": { "buildkit": true }
}

# System-Info prüfen
docker system info
docker system df  # Speicherverbrauch

# Docker-Completion für Zsh (empfohlen)
echo 'autoload -U compinit && compinit' >> ~/.zshrc

Docker Grundlagen & Konzepte

Wichtige Docker-Befehle

# Container-Management
docker ps                    # Laufende Container
docker ps -a                 # Alle Container
docker run -d nginx          # Container im Hintergrund
docker stop container_name   # Container stoppen
docker rm container_name     # Container löschen

# Image-Management  
docker images                # Lokale Images
docker pull php:8.2-apache  # Image downloaden
docker rmi image_name        # Image löschen

# System-Wartung
docker system prune          # Unused containers/images löschen
docker volume prune          # Unbenutzte Volumes löschen

Dockerfile Basics

# Beispiel: Custom PHP-Image
FROM php:8.2-apache

# System-Updates und Extensions
RUN apt-get update && apt-get install -y \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    zip \
    unzip

# PHP Extensions installieren  
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install gd pdo pdo_mysql

# Apache Rewrite-Modul aktivieren
RUN a2enmod rewrite

# Working Directory setzen
WORKDIR /var/www/html

# Ports freigeben
EXPOSE 80

LAMP-Stack mit Docker Compose

Vollständiges LAMP-Setup

# docker-compose.yml - LAMP Stack
version: '3.8'

services:
  # Apache + PHP
  web:
    build: .
    ports:
      - "8080:80"
    volumes:
      - ./src:/var/www/html
      - ./apache-config:/etc/apache2/sites-available
    depends_on:
      - db
    environment:
      - APACHE_DOCUMENT_ROOT=/var/www/html/public

  # MySQL Database
  db:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=rootpass
      - MYSQL_DATABASE=webapp
      - MYSQL_USER=webuser
      - MYSQL_PASSWORD=webpass
    volumes:
      - db_data:/var/lib/mysql
      - ./sql:/docker-entrypoint-initdb.d

  # phpMyAdmin (optional)
  phpmyadmin:
    image: phpmyadmin:latest
    ports:
      - "8081:80"
    environment:
      - PMA_HOST=db
      - PMA_USER=root
      - PMA_PASSWORD=rootpass
    depends_on:
      - db

volumes:
  db_data:

Custom Apache-Konfiguration

# apache-config/000-default.conf

    DocumentRoot /var/www/html/public
    ServerName localhost

    
        AllowOverride All
        Require all granted
        
        # Pretty URLs für Frameworks
        FallbackResource /index.php
    

    # Logging
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

PHP-Konfiguration optimieren

# Dockerfile - PHP-Settings erweitern
FROM php:8.2-apache

# Custom PHP.ini
COPY php-config/php.ini /usr/local/etc/php/

# Composer installieren
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Extensions für moderne PHP-Apps
RUN docker-php-ext-install \
    pdo_mysql \
    gd \
    zip \
    opcache \
    bcmath

# Development-Tools (nur für lokale Entwicklung)
RUN pecl install xdebug \
    && docker-php-ext-enable xdebug

LEMP-Stack (Nginx Alternative)

Nginx + PHP-FPM Setup

# docker-compose.yml - LEMP Stack
version: '3.8'

services:
  # Nginx Webserver
  nginx:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./src:/var/www/html
      - ./nginx-config/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx-config/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php

  # PHP-FPM
  php:
    build:
      context: .
      dockerfile: php.Dockerfile
    volumes:
      - ./src:/var/www/html
    environment:
      - PHP_FPM_USER=www-data
      - PHP_FPM_GROUP=www-data

  # MySQL (gleich wie LAMP)
  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=rootpass
      - MYSQL_DATABASE=webapp
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:

Nginx-Konfiguration für PHP

# nginx-config/default.conf
server {
    listen 80;
    server_name localhost;
    root /var/www/html/public;
    index index.php index.html;

    # PHP-FPM Processing
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

    # Pretty URLs
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # Security Headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
}

Node.js & React Development

Node.js Development-Setup

# docker-compose.yml - Node.js Development
version: '3.8'

services:
  # Node.js App
  node:
    image: node:18-alpine
    working_dir: /app
    ports:
      - "3000:3000"
      - "3001:3001"  # Für React Dev Server
    volumes:
      - ./:/app
      - node_modules:/app/node_modules
    command: npm run dev
    environment:
      - NODE_ENV=development
      - CHOKIDAR_USEPOLLING=true  # Für File-Watching auf macOS

  # Redis für Sessions/Caching
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"

  # PostgreSQL (Alternative zu MySQL)
  postgres:
    image: postgres:15
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=nodeapp
      - POSTGRES_USER=nodeuser
      - POSTGRES_PASSWORD=nodepass
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  node_modules:
  postgres_data:

React-App mit Docker

# Dockerfile.react - Optimiert für Development
FROM node:18-alpine

WORKDIR /app

# Package.json kopieren für besseres Caching
COPY package*.json ./
RUN npm install

# Source Code kopieren
COPY . .

# Development Server starten
EXPOSE 3000
CMD ["npm", "start"]

# Für Production Build:
# RUN npm run build
# FROM nginx:alpine
# COPY --from=0 /app/build /usr/share/nginx/html

Full-Stack JavaScript Setup

Frontend (React/Vue)

  • Node.js 18+ Container
  • Hot-Reload aktiviert
  • Port 3000 freigegeben
  • Volume für node_modules

Backend (Express/Fastify)

  • Separater Node.js Container
  • Nodemon für Auto-Restart
  • API auf Port 3001
  • Environment-Variables

Database

  • PostgreSQL oder MongoDB
  • Persistent Volumes
  • Development Seeds
  • Backup-Strategien

Database Management & Persistenz

Volume-Management für Datenbanken

# Verschiedene Volume-Arten
version: '3.8'

services:
  mysql:
    image: mysql:8.0
    volumes:
      # Named Volume (empfohlen für Production)
      - mysql_data:/var/lib/mysql
      
      # Bind Mount (gut für Development/Backup)
      - ./database/mysql:/var/lib/mysql
      
      # Init-Scripts
      - ./sql/init:/docker-entrypoint-initdb.d:ro
      
      # Custom MySQL Config
      - ./mysql-config/my.cnf:/etc/mysql/conf.d/custom.cnf:ro

volumes:
  mysql_data:
    driver: local

Database-Seeding automatisieren

# sql/init/01-schema.sql
CREATE DATABASE IF NOT EXISTS webapp;
USE webapp;

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

# sql/init/02-sample-data.sql  
USE webapp;

INSERT INTO users (name, email) VALUES
('Max Mustermann', 'max@example.com'),
('Anna Schmidt', 'anna@example.com'),
('Peter Weber', 'peter@example.com');

Multi-Database Setup

# docker-compose.yml - Verschiedene Databases
version: '3.8'

services:
  # MySQL für traditionelle Web-Apps
  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=mysql_root_pass
    volumes:
      - mysql_data:/var/lib/mysql

  # PostgreSQL für moderne Apps
  postgres:
    image: postgres:15
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=modern_app
      - POSTGRES_USER=postgres_user
      - POSTGRES_PASSWORD=postgres_pass
    volumes:
      - postgres_data:/var/lib/postgresql/data

  # MongoDB für NoSQL-Projekte
  mongodb:
    image: mongo:6
    ports:
      - "27017:27017"
    environment:
      - MONGO_INITDB_ROOT_USERNAME=mongo_user
      - MONGO_INITDB_ROOT_PASSWORD=mongo_pass
    volumes:
      - mongodb_data:/data/db

  # Redis für Caching/Sessions
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"

volumes:
  mysql_data:
  postgres_data:
  mongodb_data:

Development-Workflow & Hot-Reload

Live-Reload für PHP-Entwicklung

# docker-compose.override.yml - Development-spezifische Einstellungen
version: '3.8'

services:
  web:
    volumes:
      # Source-Code Live-Mounting
      - ./src:/var/www/html:cached
      # PHP-Config für Development
      - ./php-dev.ini:/usr/local/etc/php/conf.d/99-dev.ini
    environment:
      # Xdebug für Debugging
      - XDEBUG_MODE=develop,debug
      - XDEBUG_CONFIG=client_host=host.docker.internal client_port=9003

  # File-Watcher für Assets (optional)
  webpack:
    image: node:18-alpine
    working_dir: /app
    volumes:
      - ./assets:/app
    command: npm run watch
    depends_on:
      - web

Makefile für Docker-Workflows

# Makefile - Vereinfacht Docker-Befehle
.PHONY: up down restart logs shell install

# Docker-Services starten
up:
	docker-compose up -d

# Services stoppen
down:
	docker-compose down

# Services neu starten
restart:
	docker-compose restart

# Logs anzeigen
logs:
	docker-compose logs -f

# Shell in Container öffnen
shell:
	docker-compose exec web bash

# Dependencies installieren
install:
	docker-compose exec web composer install
	docker-compose exec webpack npm install

# Database-Backup
backup:
	docker-compose exec db mysqldump -u root -prootpass webapp > backup.sql

# Tests ausführen
test:
	docker-compose exec web ./vendor/bin/phpunit

VS Code Integration

// .vscode/settings.json - Docker Integration
{
  "php.validate.executablePath": "/usr/local/bin/php",
  "php.debug.executablePath": "/usr/local/bin/php",
  
  // Remote Container Support
  "docker.defaultRegistry": "",
  "docker.environment": {},
  
  // File-Watching optimieren
  "files.watcherExclude": {
    "**/node_modules/**": true,
    "**/vendor/**": true,
    "**/.git/objects/**": true
  }
}

Production-Ready Configurations

Multi-Stage Dockerfile

# Dockerfile - Multi-Stage für Production
# Development Stage
FROM php:8.2-apache as development
RUN docker-php-ext-install pdo_mysql gd
RUN pecl install xdebug && docker-php-ext-enable xdebug
COPY . /var/www/html

# Production Stage
FROM php:8.2-apache as production
RUN docker-php-ext-install pdo_mysql gd opcache

# Optimierte PHP-Konfiguration
COPY php-production.ini /usr/local/etc/php/conf.d/

# Security: Non-root user
RUN groupadd -g 1001 appuser && useradd -r -u 1001 -g appuser appuser
USER appuser

# Nur Production-Files kopieren
COPY --chown=appuser:appuser ./src /var/www/html
RUN composer install --no-dev --optimize-autoloader

Production docker-compose

# docker-compose.prod.yml
version: '3.8'

services:
  web:
    build:
      context: .
      target: production
    restart: unless-stopped
    environment:
      - APP_ENV=production
      - PHP_OPCACHE_ENABLE=1
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.web.rule=Host(`yourdomain.com`)"

  db:
    image: mysql:8.0
    restart: unless-stopped
    environment:
      - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/mysql_root_password
    secrets:
      - mysql_root_password
    volumes:
      - db_production:/var/lib/mysql

  nginx:
    image: nginx:alpine
    restart: unless-stopped
    volumes:
      - ./nginx-prod.conf:/etc/nginx/nginx.conf:ro

secrets:
  mysql_root_password:
    file: ./secrets/mysql_root_password.txt

volumes:
  db_production:
    driver: local

Security Best Practices

Docker Security Checklist:

  • Non-Root User: Container mit unprivilegiertem User laufen lassen
  • Secrets Management: Keine Passwörter in Dockerfiles
  • Image Scanning: docker scout cves für Vulnerabilities
  • Network Isolation: Custom Networks für Service-Isolation
  • Resource Limits: Memory/CPU-Limits setzen
  • Read-Only Filesystems: Wo möglich --read-only

Troubleshooting & Performance

Häufige macOS-spezifische Probleme

File-Sharing Performance

Problem: Langsame Volume-Mounts auf macOS

Lösung:

# Cached/Delegated Mounts verwenden
volumes:
  - ./src:/var/www/html:cached  # Host → Container optimiert
  - ./logs:/var/log:delegated   # Container → Host optimiert

# Für bessere Performance: Named Volumes
volumes:
  - source_code:/var/www/html

# Sync-Tool wie docker-sync verwenden

Memory & CPU Optimization

# docker-compose.yml - Resource Limits
version: '3.8'

services:
  web:
    image: php:8.2-apache
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M

  db:
    image: mysql:8.0
    deploy:
      resources:
        limits:
          memory: 1G
        reservations:
          memory: 512M

Docker System Monitoring

# System-Monitoring Befehle
docker system df              # Speicherverbrauch
docker system events          # Live-Events
docker stats                  # Container Resource Usage

# Container-Logs analysieren
docker-compose logs --tail=100 web
docker-compose logs -f db     # Follow-Mode

# Performance-Profiling
docker exec -it container_name top
docker exec -it container_name htop

# Network-Debugging
docker network ls
docker network inspect bridge

Backup & Disaster Recovery

# Automatisierte Backups
#!/bin/bash
# backup.sh

DATE=$(date +%Y%m%d_%H%M%S)

# Database Backup
docker-compose exec -T db mysqldump \
  -u root -prootpass webapp > "backup_${DATE}.sql"

# Volume Backup
docker run --rm \
  -v project_db_data:/data \
  -v $(pwd)/backups:/backup \
  alpine tar czf "/backup/volumes_${DATE}.tar.gz" -C /data .

# Alte Backups löschen (älter als 7 Tage)
find ./backups -name "*.sql" -mtime +7 -delete
find ./backups -name "*.tar.gz" -mtime +7 -delete

🚀 Docker-Workflow Zusammenfassung

  1. Development: docker-compose up -d
  2. Code ändern: Automatisches Reload durch Volumes
  3. Dependencies: make install (Composer/NPM)
  4. Debugging: Xdebug + VS Code Integration
  5. Testing: make test in Container
  6. Production: Multi-stage Build + Optimierung

"Docker ist wie ein guter Werkzeugkoffer – einmal richtig organisiert, findest du alles sofort und kannst überall professionell arbeiten. Der Aufwand der Einrichtung zahlt sich bei jedem neuen Projekt aus."

– Entwickler-Weisheit aus der Praxis

🎯 Für PHP-Projekte

Setup: LAMP/LEMP + phpMyAdmin
Features: Xdebug, Composer, Multi-Version
Performance: OPcache, Volume-Caching

⚛️ Für React/Node.js

Setup: Node + Hot-Reload
Features: NPM/Yarn, Live-Coding
Database: PostgreSQL, MongoDB, Redis

🏭 Für Production

Setup: Multi-Stage Builds
Security: Non-root, Secrets
Monitoring: Resource Limits, Logging

Benötigen Sie Hilfe beim Setup einer professionellen Docker-Entwicklungsumgebung für Ihr Team? Kontaktieren Sie mich für Beratung und individuelle Container-Konfigurationen.