Why Docker for Development
Docker solves the "works on my machine" problem. Every developer gets the same environment, regardless of their operating system.
Basic Setup
Here's a minimal docker-compose.yml for Laravel:
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/var/www/html
ports:
- "8000:8000"
depends_on:
- mysql
- redis
mysql:
image: mysql:8.0
environment:
MYSQL_DATABASE: app
MYSQL_ROOT_PASSWORD: secret
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
mysql_data:
The Dockerfile
Keep your Dockerfile optimized for development:
FROM php:8.3-fpm
# Install system dependencies
RUN apt-get update && apt-get install -y \
git curl zip unzip libpq-dev \
&& docker-php-ext-install pdo pdo_mysql \
&& pecl install redis \
&& docker-php-ext-enable redis
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
# Install dependencies first (cache layer)
COPY composer.json composer.lock ./
RUN composer install --no-scripts
COPY . .
CMD ["php", "artisan", "serve", "--host=0.0.0.0"]
Makefile for Common Tasks
I use a Makefile to simplify Docker commands:
up:
docker compose up -d
down:
docker compose down
shell:
docker compose exec app bash
migrate:
docker compose exec app php artisan migrate
test:
docker compose exec app php artisan test
fresh:
docker compose exec app php artisan migrate:fresh --seed
Performance Tips
Docker on macOS can be slow. Here's how to improve it:
- Use volume mounts wisely — exclude
vendorandnode_modules - Enable Docker's VirtioFS file sharing
- Use
.dockerignoreto reduce build context
Hot Reloading
For frontend development inside Docker:
node:
image: node:20-alpine
volumes:
- .:/app
working_dir: /app
ports:
- "5173:5173"
command: npm run dev -- --host
Conclusion
Docker adds a small overhead to setup, but the consistency and reproducibility it provides are worth it. Once configured, your entire team works in identical environments, and onboarding new developers becomes trivial.