Quick answer
Running a mock inside Docker Compose gives every developer and the CI pipeline the same mock on a predictable address, with no local install or version drift. A local spec server is faster to start for a single developer and easier to debug, but it depends on that machine's runtime and does not reproduce the networked environment. The reliable default is to put the mock in Compose as part of the service stack, and keep the local spec server for quick ad-hoc work. Whichever you choose, the mock definition should be a versioned spec file, not state built by hand inside a running GUI.
What each approach actually provides
| Concern | Mock in Docker Compose | Local spec server |
|---|---|---|
| Startup | One command brings the whole stack | Manual start per developer |
| Consistency | Identical image and config everywhere | Depends on local runtime version |
| Network | Real service-to-service DNS and ports | localhost only |
| Debug speed | Slightly heavier | Fastest inner loop |
| CI parity | Same Compose file runs in CI | Needs separate setup |
A Compose service backed by a spec
Mount the mock definition into a lightweight image and expose it on the internal network, so the application refers to it by service name rather than a host-specific address.
The application reads the base URL from configuration, so the same code talks to the mock locally and the real API in production with no code change. The volume is read-only, which keeps the running container from mutating the spec.
Why parity matters in CI
The biggest win is not convenience; it is eliminating the class of bugs that appear only because a developer's local mock behaved differently from what CI or staging used. When the same Compose file and the same versioned spec run in CI, a passing test means the integrated stack works, including DNS resolution, restart behavior, and the order services come up. A locally started server that a developer configured by hand cannot give that guarantee, and it makes failures hard to reproduce.
Keep the local server for the inner loop
The Compose mock is the default for integration work, but a single developer editing the spec wants a fast feedback loop. Start the same spec directly on localhost while editing, then run the full Compose stack to verify before pushing. The key is that both modes read the identical spec file, so they cannot drift; only the wrapper changes.
- Store the mock spec in version control and review it like code.
- Pin the mock image version so pulls do not silently change behavior.
- Give the mock a health check and make the app wait for it to be ready.
- Add tests that reset the mock state between runs so cases do not interfere.
Health checks and startup ordering
A depends_on relationship alone only controls start order, not readiness, so the application can attempt calls before the mock is accepting requests and fail intermittently. Give the mock service a health check that confirms the port responds, and make the application wait for that healthy state rather than a fixed sleep. This matters most in CI, where container startup timing varies and a flaky first request is otherwise hard to reproduce. Build the same readiness probe into the application's local development flow so behavior does not differ between machines. When the mock includes several stubs, add a startup log that lists the loaded spec and any seed data, which makes a misconfigured mount immediately obvious; an empty mock that returns defaults is a silent failure that can look like a passing but meaningless test. Treating the mock as a real service with health and readiness, rather than a background process assumed to be up, removes a whole class of timing-related failures.
Stateful scenarios and reset behavior
Some mocks hold state across calls, such as a created resource that later gets fetched. In Compose, define an explicit reset endpoint and call it between test cases, or recreate the container for a clean start. Do not rely on the order of tests to leave state where the next expects it, because parallel or reordered runs will then fail unpredictably. The mock should start from a known baseline every time, which is far easier to guarantee when the spec and any seed data are mounted and the container is treated as ephemeral.
FAQ
Is Docker too heavy for a single developer?
It adds some overhead, but you can keep the local spec server for fast editing and use Compose to verify the integrated stack. The point is that both read the same versioned spec, so there is no behavior drift.
How do I prevent the mock from mutating my spec files?
Mount the directory read-only and keep any runtime state inside the ephemeral container. Persistent changes belong in the spec in version control, never written back into the mounted files.
What if CI does not use Compose?
You lose the parity that makes the approach valuable. If CI cannot run Compose, pin the same mock image and spec in the pipeline so the behavior matches, even if the orchestration differs.
Should the mock ever point at production-like data?
Use synthetic seed data only. Real customer data should never be mounted into a mock, and keeping fixtures synthetic avoids both data leakage and accidental coupling to production records.
This is part of the Powerduck vs Mockoon: Mock Server and Local API Workflows — start there for the full mock-server comparison.
Comments
Join the discussionNo comments yet. Be the first to comment.

