DevOps

Getting local dev environments closer to production with Docker Compose

OPS

'Works on my machine' is still the most common bug report we get from new hires, and it almost always traces back to environment drift between laptops, whether that's a database running a different minor version, a missing environment variable that someone set locally months ago and forgot about, or a Node version mismatch that only breaks a build in ways that are hard to reproduce for anyone else. This year we finally standardized on a single Docker Compose setup for local development across every active project.

The setup cost was about a day per project, mostly spent matching database and cache versions and environment variables to what's actually running in staging rather than whatever version happened to be convenient when the project started years ago. For one older project, that meant discovering the local Postgres version everyone had been running for months was two major versions behind what staging was actually on, which explained a handful of "works locally, breaks in staging" bugs the team had been quietly living with.

Getting this right across a team with mixed operating systems took some extra care. Bind-mounted volumes on macOS were noticeably slower than the equivalent setup on Linux, enough to make hot reload feel sluggish on larger projects, and switching the mount to `:cached` or `:delegated` consistency mode closed most of that gap without giving up the convenience of editing files directly on the host machine. Windows developers on the team needed WSL2 rather than the native Docker Desktop backend to get comparable performance, which we've since made the documented default in our onboarding guide rather than something new hires discover on their own after a frustrating first week.

Seeding local databases with realistic sample data was the other piece that made this actually useful day to day, rather than just a way to run the right software versions. A single `docker compose up` followed by a seed script now gets a new hire from a fresh laptop to a working local environment with representative data in under twenty minutes on every active project, down from what used to be a half-day process involving a shared setup document that was perpetually a version or two out of date.

It's paid for itself many times over in fewer onboarding tickets and fewer afternoons lost to chasing an environment-specific bug that turned out not to exist in staging at all. The remaining friction is mostly about keeping the Compose files themselves in sync with staging as infrastructure changes, which we've started treating as part of the definition of done for any infrastructure change rather than a follow-up task that's easy to forget.

← Back to the journal

Have a project in mind?
Let’s talk.

Tell us where you are and where you want to go. We'll map the fastest route between the two.

Currently accepting new clients