Docker für Webentwickler – Container-Setup auf macOS (2025)
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.

~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
- Isolation: Jedes Projekt in eigener Umgebung
- Reproduzierbarkeit: Gleiche Umgebung überall
- Versionskontrolle: PHP 7.4 und 8.2 parallel nutzen
- Cleanup: Container löschen = sauberes System
- Production Parity: Dev-Umgebung = Production-Umgebung
- Team-Onboarding:
docker-compose upund fertig
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 cvesfü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
- Development:
docker-compose up -d - Code ändern: Automatisches Reload durch Volumes
- Dependencies:
make install(Composer/NPM) - Debugging: Xdebug + VS Code Integration
- Testing:
make testin Container - 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.