Docker Compose Local Development Setup
Docker Compose describes a multi-container environment for local development. The docker compose up command starts the entire stack: application, database, Redis, mail client.
docker-compose.yml for Laravel project
services:
app:
build:
context: .
dockerfile: docker/dev/Dockerfile
ports:
- "8000:8000"
volumes:
- .:/var/www/html # hot reload - code mounted directly
- /var/www/html/vendor # anonymous volume to avoid overwriting vendor
- /var/www/html/node_modules
environment:
APP_ENV: local
DB_HOST: db
DB_DATABASE: myapp
DB_USERNAME: myapp
DB_PASSWORD: secret
REDIS_HOST: redis
MAIL_HOST: mailpit
depends_on:
db: { condition: service_healthy }
redis: { condition: service_healthy }
command: php artisan serve --host=0.0.0.0 --port=8000
vite:
image: node:20-alpine
working_dir: /app
volumes:
- .:/app
- /app/node_modules
ports:
- "5173:5173"
command: npm run dev -- --host
db:
image: postgres:16-alpine
ports:
- "5432:5432"
environment:
POSTGRES_DB: myapp
POSTGRES_USER: myapp
POSTGRES_PASSWORD: secret
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myapp"]
interval: 5s
timeout: 3s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
mailpit:
image: axllent/mailpit:latest
ports:
- "1025:1025" # SMTP
- "8025:8025" # Web UI: http://localhost:8025
adminer:
image: adminer:latest
ports:
- "8080:8080"
environment:
ADMINER_DEFAULT_SERVER: db
depends_on: [db]
volumes:
postgres_data:
Dockerfile for development
# docker/dev/Dockerfile
FROM php:8.3-cli
RUN apt-get update && apt-get install -y \
git curl zip unzip libpq-dev \
&& docker-php-ext-install pdo_pgsql \
&& curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
WORKDIR /var/www/html
Makefile for convenient commands
# Makefile
.PHONY: up down shell artisan
up:
docker compose up -d --build
@echo "App: http://localhost:8000"
@echo "Mail: http://localhost:8025"
@echo "DB UI: http://localhost:8080"
down:
docker compose down
shell:
docker compose exec app bash
artisan:
docker compose exec app php artisan $(filter-out $@,$(MAKECMDGOALS))
tinker:
docker compose exec app php artisan tinker
test:
docker compose exec app php artisan test --parallel
migrate:
docker compose exec app php artisan migrate
fresh:
docker compose exec app php artisan migrate:fresh --seed
npm:
docker compose exec vite npm $(filter-out $@,$(MAKECMDGOALS))
# Usage
make up
make artisan make:model Product -mcr
make shell
make test
Overrides for different environments
# docker-compose.override.yml (git-ignored)
# Local developer overrides
services:
app:
environment:
XDEBUG_MODE: debug
XDEBUG_CONFIG: "client_host=host-docker-internal"
extra_hosts:
- "host.docker.internal:host-gateway"
Profiles for optional services
services:
redis-commander:
image: rediscommander/redis-commander
profiles: [tools]
ports:
- "8081:8081"
environment:
REDIS_HOSTS: local:redis:6379
# Run with additional tools
docker compose --profile tools up -d
Timeline
Docker Compose setup for typical stack (PHP + PostgreSQL + Redis + Vite): 1 day.







