CodingDevOpsIntermediate30 minSaves 30 minutes

Build a Docker Compose Local Development Stack

For engineers needing consistent local environments, this prompt generates a Docker Compose setup with application, database, caching, and email services, ensuring reliable startup and data persistence.

Generate a full Docker Compose configuration for a local development environment, integrating your application, PostgreSQL, Redis, and MailHog. It includes named volumes for data persistence, a `wait-for-db` entrypoint for service reliability, and provides essential guidance on image size and security for a robust setup.

READY-TO-USE PROMPT

Copy Prompt

prompt.txt
Role: You are a seasoned Platform Engineer specializing in creating reproducible and secure local development environments.

Context: I am setting up a new local development environment for a web application. The stack requires an application service (e.g., Node.js, Python, Ruby), a PostgreSQL database, a Redis caching layer, and MailHog for email testing. Consistency, data persistence, and proper service startup order are critical for developer efficiency and avoiding "works on my machine" issues. The environment must be easy to spin up and tear down, while also providing insights into best practices for image size and security.

Task: Generate a comprehensive Docker solution that includes all necessary files and guidance for this local development stack. Provide:
1.  A `Dockerfile` for a generic application service, demonstrating best practices for build efficiency and image size. Assume the application code resides in the current directory.
2.  A `docker-compose.yml` file orchestrating the application, PostgreSQL, Redis, and MailHog. This file must:
    *   Define services for `app`, `db`, `redis`, and `mailhog`.
    *   Use named volumes for persistent data storage for PostgreSQL and Redis.
    *   Implement a `wait-for-db` entrypoint script for the application service to ensure the database is ready before the application attempts to connect.
    *   Expose necessary ports (e.g., for the application, MailHog UI).
    *   Set up environment variables for database connection details.
3.  Detailed `build and runtime notes` explaining how to build, run, and manage the stack, including common commands and troubleshooting tips.
4.  Specific `image size targets` for the application Dockerfile, outlining strategies to minimize image bloat (e.g., multi-stage builds, `.dockerignore`).
5.  Essential `security notes` for a local development environment, covering aspects like credential management, host bind mounts, and network isolation.

Constraints:
*   The `docker-compose.yml` must use version "3.8" or higher.
*   PostgreSQL and Redis services should use official Docker images.
*   The application Dockerfile should be multi-stage if applicable for a generic web app (e.g., build stage, runtime stage).
*   The `wait-for-db` script should be robust, checking for database readiness rather than just port availability.
*   All generated code should be ready to use without further modification, assuming the placeholders are populated.

Output Format:
Present the solution with clear headings for each section:
*   `Dockerfile` (for the application)
*   `wait-for-db.sh` (script)
*   `docker-compose.yml`
*   `Build and Runtime Notes`
*   `Image Size Targets`
*   `Security Notes`

Ensure all code blocks are properly formatted.

Placeholders:
*   `{{application_name}}`: A short, descriptive name for your application (e.g., `my-webapp`).
*   `{{application_port}}`: The port your application listens on within its container (e.g., `3000`, `8000`).
*   `{{database_user}}`: The username for the PostgreSQL database (e.g., `dev_user`).
*   `{{database_password}}`: The password for the PostgreSQL database (e.g., `dev_password`).
*   `{{database_name}}`: The name of the PostgreSQL database (e.g., `my_app_db`).

Estimated results

DifficultyIntermediate
Setup time30 min
Time saved30 minutes
Best modelsChatGPT, Gemini, Claude
Best audienceSoftware Development, DevOps

Editor's note

Why this prompt matters

Local development environment inconsistencies are a persistent source of friction for engineering teams. The classic 'works on my machine' scenario often stems from differing dependency versions, missing services, or subtle configuration discrepancies between developer machines. This drift not only wastes valuable development time but also introduces instability into the delivery pipeline, as issues only surface later in integration or staging environments. A reliable, reproducible local stack is foundational for productive engineering work, ensuring that every developer operates on a consistent baseline.

This workflow directly addresses these challenges by providing a structured Docker Compose setup. It orchestrates common application components—your main service, a PostgreSQL database, Redis for caching, and MailHog for local email testing—into a cohesive unit. By encapsulating these services, developers gain a predictable environment that mirrors production more closely, reducing the cognitive load of managing individual services. Crucially, it establishes proper service startup order and persistent data storage, eliminating the need to reconfigure or repopulate databases after each restart.

Furthermore, this approach emphasizes operational best practices from the outset. It includes guidance on minimizing Docker image sizes for faster builds and deployments, and critical security considerations for a local context. Understanding how to manage credentials, isolate networks, and handle bind mounts even in development is key to fostering a security-aware mindset that extends beyond the local machine. This setup provides a solid foundation, allowing engineers to focus on application logic rather than environment setup.

Anatomy

Prompt engineering breakdown

Role

You are a seasoned Platform Engineer specializing in creating reproducible and secure local development environments.

Context

I am setting up a new local development environment for a web application. The stack requires an application service (e.g., Node.js, Python, Ruby), a PostgreSQL database, a Redis caching layer, and MailHog for email testing. Consistency, data persistence, and proper service startup order are critical for developer efficiency and avoiding "works on my machine" issues. The environment must be easy to spin up and tear down, while also providing insights into best practices for image size and security.

Goal

Generate a comprehensive Docker solution that includes all necessary files and guidance for this local development stack. Provide: 1. A `Dockerfile` for a generic application service, demonstrating best practices for build efficiency and image size. 2. A `docker-compose.yml` file orchestrating the application, PostgreSQL, Redis, and MailHog. 3. Detailed `build and runtime notes`. 4. Specific `image size targets`. 5. Essential `security notes`.

Constraints

The `docker-compose.yml` must use version "3.8" or higher. PostgreSQL and Redis services should use official Docker images. The application Dockerfile should be multi-stage if applicable for a generic web app (e.g., build stage, runtime stage). The `wait-for-db` script should be robust, checking for database readiness rather than just port availability. All generated code should be ready to use without further modification, assuming the placeholders are populated.

Output format

Present the solution with clear headings for each section: `Dockerfile`, `wait-for-db.sh`, `docker-compose.yml`, `Build and Runtime Notes`, `Image Size Targets`, `Security Notes`. Ensure all code blocks are properly formatted.

Why this structure works

Role priming establishes the model's persona as a seasoned Platform Engineer, ensuring expert-level solutions. Explicit constraints guide the model on specific Docker Compose versions, image choices, and the robustness of the wait-for-db script. Structured output guarantees all required components are delivered in a clear, organized manner, simplifying adoption for developers.

Pick your version

Prompt variations

BeginnerWorks with any model

For new developers or those unfamiliar with Docker Compose, needing a basic but functional setup without extensive advanced configurations.

prompt.txt
As a developer, I need a basic Docker Compose setup for my web application. It should include my app, a PostgreSQL database, Redis, and MailHog for testing emails. I want to easily start and stop the environment. Make sure the database data is saved, and the app waits for the database to be ready. Provide a simple Dockerfile for my app, a `docker-compose.yml` file, and instructions on how to run it. Keep the explanations clear and straightforward. Use official images for PostgreSQL and Redis.
Placeholders: `{{application_name}}`, `{{application_port}}`, `{{database_user}}`, `{{database_password}}`, `{{database_name}}`
ProfessionalBest with claude

For experienced developers or DevOps engineers seeking a comprehensive, best-practice driven local development setup with detailed guidance on optimization and security.

prompt.txt
As a Platform Engineer, I need a robust and reproducible local development environment. The stack requires an application service (e.g., Node.js, Python, Ruby), PostgreSQL, Redis, and MailHog. Prioritize consistency, data persistence via named volumes, and proper service startup order using a `wait-for-db` entrypoint. Generate a multi-stage `Dockerfile` for the generic application, a `docker-compose.yml` (version 3.8+), detailed build/runtime notes, image size optimization strategies, and essential local security notes. Ensure all code is production-ready, using official images for `db` and `redis`.
Placeholders: `{{application_name}}`, `{{application_port}}`, `{{database_user}}`, `{{database_password}}`, `{{database_name}}`
Short VersionBest with chatgpt

When a quick, concise Docker Compose setup is needed without extensive explanations or detailed guidance, ideal for rapid prototyping.

prompt.txt
Provide a Docker Compose solution for a local development environment. I need an `app` service, PostgreSQL, Redis, and MailHog. The `docker-compose.yml` should use named volumes for persistence and include a `wait-for-db` script for the app to ensure the database is ready. Also, generate a basic multi-stage `Dockerfile` for the app. Use `{{application_name}}`, `{{application_port}}`, `{{database_user}}`, `{{database_password}}`, and `{{database_name}}` as placeholders. Keep the output concise, focusing on the essential files and commands to get started quickly.
EnterpriseBest with gemini

For organizations where local development environments must align with corporate standards, security policies, and stakeholder expectations, emphasizing compliance and risk mitigation.

prompt.txt
As a Senior Platform Architect, I require a Docker Compose local development stack adhering to enterprise compliance and security standards. The solution must integrate an application service, PostgreSQL, Redis, and MailHog, emphasizing maintainability, auditability, and minimal operational risk. Generate a comprehensive `Dockerfile` (multi-stage, optimized for image size and security scanning), a `docker-compose.yml` (version 3.8+, named volumes, robust `wait-for-db`), detailed operational runbooks, and explicit security hardening recommendations. Address considerations for credential management, host bind mount policies, and network segmentation to mitigate corporate data exposure risks. Ensure the setup is easily reviewable by security and compliance stakeholders.
Placeholders: `{{application_name}}`, `{{application_port}}`, `{{database_user}}`, `{{database_password}}`, `{{database_name}}`

What you'll get

Expected output

```dockerfile # Stage 1: Build environment FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm install --omit=dev COPY . . # Assuming a build step for a typical web application # RUN npm run build

# Stage 2: Runtime environment FROM node:20-alpine WORKDIR /app COPY --from=builder /app/node_modules ./node_modules # COPY --from=builder /app/dist ./dist # Example for compiled assets COPY package*.json ./ COPY .env.example .env # Example .env file for local dev EXPOSE 3000 CMD ["node", "index.js"] # Adjust to your application's entry point ```

```yaml version: '3.8'

services: app: build: context: . dockerfile: Dockerfile ports: - "3000:3000" environment: DATABASE_URL: postgres://user:password@db:5432/mydb REDIS_HOST: redis SMTP_HOST: mailhog SMTP_PORT: 1025 depends_on: db: condition: service_healthy volumes: - ./wait-for-db.sh:/usr/local/bin/wait-for-db.sh entrypoint: ["/usr/local/bin/wait-for-db.sh", "db", "5432", "node", "index.js"]

db: image: postgres:15-alpine restart: always environment: POSTGRES_USER: user POSTGRES_PASSWORD: password POSTGRES_DB: mydb volumes: - pg_data:/var/lib/postgresql/data ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U user -d mydb"] interval: 5s timeout: 5s retries: 5

redis: image: redis:7-alpine restart: always volumes: - redis_data:/data ports: - "6379:6379"

mailhog: image: mailhog/mailhog:latest ports: - "8025:8025" # Web UI - "1025:1025" # SMTP server

volumes: pg_data: redis_data: ```

```bash #!/bin/sh # wait-for-db.sh

host="$1" port="$2" shift 2 cmd="$@"

>&2 echo "Waiting for $host:$port to be ready..."

until PGPASSWORD="password" psql -h "$host" -U "user" -d "mydb" -c '\q'; do >&2 echo "PostgreSQL is unavailable - sleeping" sleep 1 done

>&2 echo "PostgreSQL is up - executing command" exec $cmd ```

Build and Runtime Notes

To initialize the environment, build the images with docker compose build. Then, start all services in detached mode using docker compose up -d. Monitor service logs via docker compose logs -f. To halt and remove containers, networks, and persistent volumes, run docker compose down -v. For debugging, access a container shell with docker compose exec [service_name] sh.

Image Size Targets

Target application image sizes under 100MB. Employ multi-stage Dockerfiles to separate build-time dependencies from the final runtime image. Use a .dockerignore file to exclude development artifacts, test files, and version control directories from the build context. Select minimal base images, such as Alpine variants, to reduce the initial footprint.

Security Notes

Avoid embedding sensitive credentials directly in Dockerfiles or docker-compose.yml for any environment beyond isolated local development. Use .env files for local secrets, ensuring they are not committed to source control. Restrict host bind mounts to only necessary directories and avoid exposing sensitive host paths. Use Docker Compose's default network isolation or custom networks to control inter-service communication.

Under the hood

Why this prompt works

This prompt effectively guides the model to produce a complete Docker Compose development stack by employing several targeted techniques.

First, the Role instruction establishes a clear persona: a 'seasoned Platform Engineer.' This frames the model's output with an authoritative, ops-minded perspective, ensuring best practices for security and maintainability are prioritized.

Second, the Context section provides essential background, detailing the specific services required (app, PostgreSQL, Redis, MailHog) and the critical non-functional requirements like consistency, data persistence, and service startup order. This detailed scenario eliminates ambiguity and focuses the model on the user's exact needs.

Third, the Task breakdown is highly granular, explicitly listing five distinct deliverables. Each point acts as a sub-prompt, directing the model to generate specific files (Dockerfile, docker-compose.yml) and crucial guidance (build and runtime notes, image size targets, security notes). This structured approach ensures comprehensive coverage of the request.

Within the Task and Constraints, specific technical requirements are embedded. For instance, requiring 'named volumes for persistent data storage' and a 'robust wait-for-db entrypoint script' pushes the model beyond basic functionality toward production-grade solutions. Similarly, mandating 'multi-stage builds' and 'security notes' directly addresses the user's need for efficient and secure environments. These explicit instructions prevent generic outputs and ensure the generated solution aligns with current development and security standards.

Model fit

Best AI models for this prompt

Claude

Claude models excel at generating structured code and detailed explanations. Their strong context window allows for comprehensive instructions regarding Docker Compose service definitions, entrypoint scripts, and multi-stage Dockerfiles. The ability to handle intricate constraints makes it effective for producing accurate and well-commented configurations, along with the required operational and security guidance. See the full Claude hub for deeper guidance.

ChatGPT

ChatGPT models are proficient in producing functional code snippets and explaining complex technical concepts. They are capable of generating the docker-compose.yml, Dockerfile, and wait-for-db.sh script, alongside clear build/runtime instructions. While generally reliable, it's always advisable to review the generated security notes for specific environment applicability. See the full ChatGPT hub for deeper guidance.

Gemini

Gemini models are strong at understanding and executing multi-part technical requests, making them suitable for generating a complete Docker solution. They handle code generation for various components like Dockerfiles and Compose files effectively, and can articulate best practices for image optimization and security. Reviewing the wait-for-db script logic for specific database interaction is a good practice. See the full Gemini hub for deeper guidance.

When to use

  • When initializing a new web application project requiring multiple interconnected services (e.g., application, database, cache).
  • To standardize development environments, ensuring all team members work with identical service configurations and dependencies.
  • For projects where data persistence for local databases (PostgreSQL, Redis) is critical across container restarts.
  • When needing to test email functionality locally without sending actual emails, using tools like MailHog.
  • To streamline the onboarding process for new developers, providing a ready-to-run local stack.

When not to use

  • For production deployments; this setup lacks production-grade security, scalability, and monitoring.
  • If your application is a single, self-contained service with no external dependencies.
  • On systems with extremely limited resources, where the overhead of multiple containers might degrade performance significantly.
  • When all application dependencies are managed entirely by external cloud services, negating the need for local orchestration.

Get more from it

Pro tips

  • 1

    Always use named volumes for database persistence to prevent data loss when containers are removed, ensuring development data stability.

  • 2

    Implement explicit health checks in `docker-compose.yml` to ensure services are truly ready before dependent services attempt connections, avoiding startup errors.

  • 3

    Regularly prune unused Docker images, containers, and volumes to reclaim disk space and maintain a clean development environment.

  • 4

    Bind mount application code for live reloading during development; this accelerates iteration cycles by reflecting code changes instantly.

  • 5

    Customize `wait-for-db.sh` scripts for specific database readiness checks beyond basic port availability, preventing premature application startup.

  • 6

    Utilize `.dockerignore` effectively to prevent unnecessary files from being copied into your image, reducing build context size and final image bloat.

Don't ship this

Common mistakes

  • Hardcoding sensitive credentials directly within the `docker-compose.yml` file.

    Fix — Use environment variables loaded from a `.env` file or `env_file` directive for better security practices and flexibility.

  • Neglecting to use named volumes for database data persistence.

    Fix — Define and attach named volumes to database containers to ensure data persists across container restarts and removals.

  • Forgetting to create a `.dockerignore` file for the application service.

    Fix — Create a `.dockerignore` file to exclude development dependencies and unnecessary files, reducing image size and build time.

  • Relying solely on `depends_on` for service startup order, which only checks container startup, not readiness.

    Fix — Implement `wait-for-db` scripts or similar health checks to verify actual service readiness before dependent services connect.

  • Exposing all internal container ports to the host machine indiscriminately.

    Fix — Only map necessary ports for host access. Keep internal service communication on the isolated Docker network.

  • Building large, bloated application Docker images by copying unnecessary files or using inefficient build processes.

    Fix — Employ multi-stage builds and minimize layers. Copy only essential runtime artifacts into the final, smaller image.

People also ask

Frequently asked questions

Q.Can I use this Docker Compose setup for staging or production environments?

No, this setup is strictly for local development. Production environments require robust solutions for scalability, high availability, advanced security, and comprehensive monitoring, which this local configuration does not provide.

Q.How do I ensure my database data isn't lost when I rebuild or remove containers?

The docker-compose.yml uses named volumes for PostgreSQL and Redis. As long as you don't explicitly remove these volumes using docker volume rm, your data will persist across container lifecycle events.

Q.My application container starts but cannot connect to the database, causing errors. What's the common issue?

This often occurs if the application starts before the database is fully initialized. Ensure the wait-for-db.sh script is correctly implemented as the application container's entrypoint and effectively checks for database readiness.

Q.What is the recommended approach for managing environment variables for different developers or specific scenarios?

Place a .env file at your project's root. Docker Compose automatically loads variables from it. For more specific needs, use the env_file directive within your docker-compose.yml service definitions.

Q.How can I effectively reduce the final size of my application's Docker image?

Utilize multi-stage builds, ensuring only the necessary runtime artifacts are copied to the final, smaller base image. Also, maintain a comprehensive .dockerignore file to exclude irrelevant files during the build process.

Q.Is it secure to use simple passwords like 'dev_password' for databases in a local development setup?

For local development, simple passwords are common. However, never reuse these credentials in any non-development environment. Always ensure .env files containing credentials are not committed to version control.

Version 1.0Last reviewed July 20, 2026
Reviewed by PromptInFlow Editorial Team