For Postgres, the canonical Compose service sets POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB environment variables to create a database on first run, mounts a named volume on /var/lib/postgresql/data for persistence, mounts SQL or shell files into /docker-entrypoint-initdb.d/ for one-time initialization, and defines a healthcheck using pg_isready -U postgres. The MySQL equivalents are MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, MYSQL_USER, and MYSQL_PASSWORD. To back up a Postgres database, run docker compose exec db pg_dump -U postgres -d mydb > backup.sql; to restore, run docker compose exec -T db psql -U postgres -d mydb < backup.sql.
For Redis, persistence is opt-in via command-line flags: command: ['redis-server', '--appendonly', 'yes'] plus a volume on /data turns on append-only file persistence, and --requirepass sets a password. For MongoDB, set MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD to enable authentication on first start. RabbitMQ's default guest/guest credentials only work from localhost; for real credentials, mount a definitions file or use the RABBITMQ_DEFAULT_USER and RABBITMQ_DEFAULT_PASS environment variables. Elasticsearch in development is happy with discovery.type=single-node and xpack.security.enabled=false in its environment. Kafka in KRaft mode (no Zookeeper) is easiest with the bitnami image and a few KAFKA_* environment variables. For Nginx serving a static SPA, the typical recipe mounts the build output to /usr/share/nginx/html read-only and configures a try_files fallback to index.html so client-side routes work.
Common developer tooling stacks have well-trodden patterns. A LAMP-style setup links php-fpm, nginx (mounting a site.conf file), and mysql (with a volume and env) over the default Compose network. A Laravel app typically runs php-fpm, nginx, mysql, redis, and a queue worker as its own service running php artisan queue:work. A Rails app combines web (puma), sidekiq, postgres, and redis, with an optional Chrome service for system tests. A Django app runs gunicorn, celery worker, celery beat, postgres, and redis, with flower as an optional monitoring service. A Next.js dev environment runs next dev with postgres and an anonymous volume on node_modules. A FastAPI setup runs uvicorn with --reload plus postgres. For dev tooling, MailHog catches outgoing email on ports 1025 (SMTP) and 8025 (UI), Adminer provides a database GUI on port 8080 reachable via the compose service name as host, and reverse proxies like Traefik or Caddy attach via labels or mounted config files to route traffic. For Go and Python hot-reload, the cosmtrek/air image or uvicorn --reload handle the rebuild loop inside the container. As a general rule, keep the base docker-compose.yml committed to git for reproducibility while gitignoring docker-compose.override.yml so each developer can customize without conflicting.