Jun 29, 2025My Local Dev Setup: How I Stopped Fighting Docker and Made Peace
The War of the Ports
When Docker (port 80) declared war on Laravel Valet (also port 80), my development environment became a battlefield. Key casualties:
- Project A: Laravel app refusing to connect to MySQL
- Project B: WordPress site showing 'Error establishing database connection'
- My Sanity: Lost in
docker-compose logsoutput
I was rebooting containers like a caffeinated sysadmin and still couldn’t get `localhost` to behave. One day, I had both Docker and Valet running, and my browser served me a 502 Bad Gateway from the wrong app. It felt like walking into your house and finding a stranger watching Netflix on your couch. Boundaries were being crossed. Ports were being hijacked. It was time to act.
The Peace Treaty
The solution came after hours of trial, error, and a brief spiral into minimalism where I considered building everything in Bash just to avoid Docker entirely. But reason prevailed:
# docker-compose.yml - The Armistice Agreement
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "${APP_PORT:-8080}:80" # Compromise: No more port 80 greed
networks:
- sail
volumes:
- '.:/var/www/html'
networks:
sail:
driver: bridge
This tiny change—moving away from port 80—restored peace. Laravel Valet could keep its throne on 80, and Docker could live happily on 8080. I stopped treating my local machine like a zero-sum game and started respecting the boundaries between tools.
Current Stack Allocation
| Tool | Use Case | When to Avoid |
|---|---|---|
| Docker | Microservices, team projects | Quick PHP script tests |
| Valet | Legacy projects, local WordPress | When you need containerization |
| Node + npm scripts | Frontend builds and hot reload | API mocking across services |
Other Truces I Had to Negotiate
- MySQL 8 vs MariaDB: They look alike until you import a dump and everything breaks.
- Volume mounts on Mac: Slower than molasses if not tuned. I switched to cached mounts and gained back hours of my life.
- CORS: Not a Docker issue, but it always shows up when you’re already frustrated. Like a parking ticket after a long day.
"The best tool is the one you'll actually use. My setup now looks chaotic but works like a Swiss watch—if Swiss watches occasionally needed docker system prune."
How I Onboard New Projects Now
Every new project starts with a checklist:
- Can this run in Valet without side effects? Great. Use Valet.
- Need multiple services or team parity? Spin up Docker.
- Does it require a custom port? Block it in advance.
- Are we exposing 3306 again? Alias it. Always alias it.
I keep a running log of my local ports in a `README-local.md` and document the startup sequence like it’s a NASA launch. Because nothing derails momentum like forgetting that your frontend expects the API on port 5173—but you’re actually running it on 8081 today because your other project refused to shut down properly.
The Bigger Lesson
This whole saga wasn’t really about Docker or Valet. It was about context switching, managing dev fatigue, and accepting that your local machine is not a clean lab environment. It’s a battlefield with layers of tooling piled on like sedimentary rock. And if you don’t pause to make sense of it, eventually you’re knee-deep in logs wondering why `localhost:8000` now returns a WordPress homepage from 2021.
The real upgrade wasn’t just the yml file—it was learning to zoom out. To ask: what does this project need? What do I need to stay productive? Sometimes it’s a bash script. Sometimes it’s a new network alias. Sometimes it’s a deep breath and a walk around the block before you hit ⌘+R one more time.
Lessons & Reflections
- Don't fight your tools—reconfigure them with empathy for your future self.
- Write down the weird hacks. You’ll thank yourself a month later.
- Ports aren’t just numbers—they’re personalities. Some get along. Some absolutely don’t.
This post offered an unexpected lens into the topic of "My Local Dev Setup: How I Stopped Fighting Docker and Made Peace"—something I initially underestimated. What began as a routine story evolved into a surprisingly personal audit of where I’ve grown, where I’ve slipped, and what continues to challenge me. I realized that my path hasn't been about linear progress; it’s been a series of weird detours, punchline errors, and the occasional small win that gave me just enough momentum to keep going.
If there's a takeaway, it’s this: context matters. The same challenge that might’ve broken me five years ago now feels like a teachable moment. And maybe that’s the definition of growth. Thanks for sticking with the post—I hope your own journey is full of equally ridiculous, humbling, and surprisingly meaningful moments.