Write me a `docker-compose.yml` for local development that actually works for a real project — not the official 'hello world' example.
SERVICES NEEDED: {list — app, db, cache, queue, etc.}
APP TECH: {Node/Python/Rust/Go + framework}
DB: {Postgres / MySQL / Mongo / etc. + version}
CACHE: {Redis / Memcached / none}
QUEUE / MESSAGING: {RabbitMQ / Kafka / none}
OTHER SERVICES: {Elasticsearch / Mailhog / S3-compatible / etc.}
VOLUMES / PERSISTENCE: {DB data should persist between docker compose down}
HOT RELOAD: {do you want code changes to reflect without rebuild}
EXISTING ENV VARS: {.env file? if so, briefly summarize}
OS THE TEAM USES: {Mac / Linux / mixed}
KNOWN PAIN: {volume mount perf / port conflicts / DB startup race}
DELIVER:
1. **Complete docker-compose.yml** — runnable, no `# TODO` placeholders.
2. **Sane defaults**: healthchecks, depends_on with conditions (not just service order), restart policies for dev.
3. **Hot reload setup** for the app service if requested.
4. **`.env.example`** template to commit.
5. **One README snippet** — `docker compose up` then the 3 things a new dev needs to know.
6. **3 common gotchas** specific to this stack + how to avoid them.
7. **Cleanup command** — how to wipe everything (volumes included).0 copies·0 saves·1 views
201 words·1,256 chars
Sample output
Services: Next.js app + Postgres + Redis + Mailhog (for catching dev emails). App: Node 20, Next.js with file-watch hot reload. DB: Postgres 16. Cache: Redis 7. Persistence: Postgres data persists, Redis can be ephemeral. Hot reload: yes. Env: existing .env.local. OS: mixed Mac + Linux. Pain: volume mount perf on Mac, Postgres race condition where app starts before DB is ready.
1. docker-compose.yml:
version: '3.9'
services:
postgres:
image: postgres:16-alpine
container_name: app_postgres
environment:
POSTGRES_USER: ${POSTGRES_USER:-app}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-app}
POSTGRES_DB: ${POSTGRES_DB:-app_dev}
ports:
- '5432:5432'
volumes:
- postgres_data:/var/lib/postgresql/data
- ./scripts/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER:-app}']
interval: 5s
timeout: 3s
retries: 10
restart: unless-stopped
redis:
image: redis:7-alpine
container_name: app_redis
ports:
- '6379:6379'
command: redis-server --save "" --appendonly no
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
mailhog:
image: mailhog/mailhog:latest
container_name: app_mailhog
ports:
- '1025:1025'
- '8025:8025'
restart: unless-stopped
app:
build:
context: .
dockerfile: Dockerfile.dev
container_name: app_web
ports:
- '3000:3000'
environment:
NODE_ENV: development
DATABASE_URL: postgresql://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:-app}@postgres:5432/${POSTGRES_DB:-app_dev}
REDIS_URL: redis://redis:6379
SMTP_HOST: mailhog
SMTP_PORT: 1025
volumes:
- ./:/usr/src/app
- /usr/src/app/node_modules
- /usr/src/app/.next
depends_on:
postgres: { condition: service_healthy }
redis: { condition: service_healthy }
mailhog: { condition: service_started }
restart: unless-stopped
volumes:
postgres_data:
name: app_postgres_data
Parameters
Text generation parameters
FAQ
Always commit the `Dockerfile.dev` — not `Dockerfile` — and have a separate production `Dockerfile`. Devs reach for the existing Dockerfile and end up shipping `pnpm dev` to prod. The prompt targets ChatGPT (GPT-4) and lives in the Coding & Development category on mycopyprompt.
This prompt is written for ChatGPT (GPT-4). It's a text/chat prompt — paste it into ChatGPT (GPT-4) (or compatible LLMs like Claude or GPT-4) to get the expected output.
1. Click the Copy button on this page to copy the full prompt. 2. Open ChatGPT (GPT-4). 3. Paste the prompt into a new conversation. 4. Replace any {placeholders} with your specifics, then send. Most prompts produce the right output on the first try; complex ones may need 1-2 iterations.
Yes — every prompt on mycopyprompt is free forever. No paywall, no signup wall for browsing or copying. You can use it for personal or commercial work, just don't redistribute the entire mycopyprompt library.
Absolutely — most prompts are templates. Look for {placeholders} (curly braces) and swap them with your own values. You can also reword sections, add constraints, or chain it with other prompts.
See the "Sample output" panel above — that's a real example of what ChatGPT (GPT-4) returns when this prompt runs. Your output will vary in wording but should follow the same structure and depth.
Similar prompts
Matched against every prompt in the catalog by title.
Dockerfile.dev:
FROM node:20-alpine
WORKDIR /usr/src/app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm@9 && pnpm install --frozen-lockfile
COPY . .
EXPOSE 3000
CMD ["pnpm", "dev"]
2. Healthchecks + depends_on with conditions: ✓ done above. App waits for Postgres healthcheck to PASS, not just for Postgres container to start. That's the difference between 'app sometimes crashes on first start' and 'app always works.'
3. Hot reload: ✓ Next.js dev server in app container + volume mount of repo root. Note the two anonymous volumes for node_modules and .next — these prevent the host's empty node_modules from overwriting the container's installed deps.
4. .env.example:
# Postgres
POSTGRES_USER=app
POSTGRES_PASSWORD=app
POSTGRES_DB=app_dev
# App-level (these will be in your .env.local for the app)
NEXTAUTH_SECRET=local_dev_only_change_me
NEXTAUTH_URL=http://localhost:3000
5. README snippet:
## Local dev
```bash
cp .env.example .env
docker compose up
First run takes 2-3 min for Postgres init and pnpm install. Subsequent docker compose up is fast.
To wipe everything (incl. DB data): docker compose down -v
**6. Gotchas for this stack:**
1. **Mac volume mount perf:** Mounting your entire repo into the container kills file-watcher performance on Mac. **Fix:** use `:cached` mount flag for read-heavy paths if on Docker 4+:
```yaml
volumes:
- ./:/usr/src/app:cached
Or use OrbStack instead of Docker Desktop on Mac — significantly better mount performance.
Postgres race condition: Next.js dev server can start before Postgres is accepting connections (even after the container is 'running'). The healthcheck + depends_on: { condition: service_healthy } we set above fixes this. If you remove the healthcheck, you'll get random 'ECONNREFUSED' on first start.
node_modules confusion: Local node_modules clashing with container node_modules is the #1 cause of 'works on my machine'. The anonymous volume /usr/src/app/node_modules keeps them separate. If your team installs new deps frequently, run docker compose run --rm app pnpm install instead of installing locally + rebuilding.
7. Cleanup:
docker compose down -v # stop + remove volumes (wipes DB)
docker compose down # stop, keep DB data
docker system prune -a # purge all unused images (do this monthly)