Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/LENINMORENO13/OpsMind/llms.txt

Use this file to discover all available pages before exploring further.

OpsMind ships as a fully containerised application. A single docker-compose.yml spins up both the Postgres database and the API server with one command, making local development and staging environments easy to reproduce. For production, the same Dockerfile is used by the live instance hosted on Render, and it can be deployed to any Docker-compatible platform with minimal configuration.

Local deployment with Docker Compose

The docker-compose.yml file defines two services that work together:
  • db — a postgres:15-alpine container that runs on host port 5433 (mapped from container port 5432). The database name, user, and password are set via POSTGRES_* environment variables. A named volume (db_data) is mounted at /var/lib/postgresql/data to persist data across container restarts.
  • api — the OpsMind API built from the local Dockerfile, exposed on port 3000:3000. It depends on db and connects to it over the Docker bridge network using the service hostname db.
Start all services
docker compose up --build
Stop all services
docker compose down
To tear down containers and delete all persisted database data:
Remove containers and volumes
docker compose down -v
docker-compose.yml
services:
  db:
    image: postgres:15-alpine
    container_name: opsmind-postgres
    restart: always
    environment:
      POSTGRES_USER: lenin_dev
      POSTGRES_PASSWORD: password123
      POSTGRES_DB: opsmind_db
    ports:
      - "5433:5432"
    volumes:
      - db_data:/var/lib/postgresql/data

  api:
    build: .
    container_name: opsmind-api
    restart: always
    ports:
      - "3000:3000"
    depends_on:
      - db
    environment:
      JWT_SECRET: "mi_secreto_super_bloqueado_2026"
      DATABASE_URL: "postgresql://lenin_dev:password123@db:5432/opsmind_db?schema=public"
      GEMINI_API_KEY: "${GEMINI_API_KEY}"

volumes:
  db_data:
The JWT_SECRET value "mi_secreto_super_bloqueado_2026" in docker-compose.yml is a development placeholder only. In production, set JWT_SECRET to a long, randomly-generated string that is never committed to source control. A compromised secret allows anyone to forge valid tokens.

What the Dockerfile does

The Dockerfile builds a lean, single-stage image on top of node:20-alpine.
Dockerfile
FROM node:20-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY prisma ./prisma
RUN npx prisma generate

COPY . .

EXPOSE 3000

CMD npx prisma db push && npm start
1

Base image

node:20-alpine provides a minimal Node.js 20 environment. The Alpine base keeps the final image small.
2

Install dependencies

package*.json is copied first — before the rest of the source — so that Docker’s layer cache is reused on subsequent builds when only application code changes.
3

Generate the Prisma client

npx prisma generate is run while only the prisma/ directory is in scope, again to maximise cache efficiency. This compiles the type-safe Prisma client from schema.prisma.
4

Copy source and expose the port

The remainder of the application is copied and port 3000 is declared.
5

Startup command

The CMD runs npx prisma db push && npm start in sequence. db push synchronises the Prisma schema to the connected database before the Express server starts.

Database migrations

prisma db push (run automatically on startup) introspects prisma/schema.prisma and applies any missing tables or columns directly to the target database without generating a migration file. This is convenient for development and the current production deployment, but it is not recommended for teams that need a versioned migration history. For production environments that require auditable, reversible migrations:
1

Generate a migration

Terminal
npx prisma migrate dev --name descriptive_name
This creates a timestamped SQL file inside prisma/migrations/.
2

Apply migrations in production

Terminal
npx prisma migrate deploy
migrate deploy applies only pending migration files in sequence. It never prompts interactively and is safe to run in CI/CD pipelines and container startup scripts.

Environment variables

OpsMind requires three environment variables at runtime. See the configuration reference for full details.
VariableRequiredDescription
DATABASE_URLPostgreSQL connection string in Prisma URL format
JWT_SECRETSecret used to sign and verify JWT tokens
GEMINI_API_KEYGoogle Gemini API key for AI incident analysis
A minimal .env file for local development without Docker looks like this:
.env
PORT=3000
DATABASE_URL="postgresql://postgres:YOUR_PASSWORD@localhost:5432/opsmind_db?schema=public"
GEMINI_API_KEY=your_gemini_api_key_here
In docker-compose.yml, the GEMINI_API_KEY is forwarded from the host environment using "${GEMINI_API_KEY}". Set it in your shell before running docker compose up:
Terminal
export GEMINI_API_KEY=your_gemini_api_key_here
docker compose up --build

Production deployment

The live OpsMind API is hosted at https://opsmind-e07b.onrender.com on Render. Render detects the Dockerfile at the repository root and builds the image on every push to main. Environment variables (DATABASE_URL, JWT_SECRET, GEMINI_API_KEY) are configured in the Render dashboard under the service’s Environment tab. To deploy OpsMind to any Docker-compatible platform:
1

Build and push the image

Terminal
docker build -t your-registry/opsmind:latest .
docker push your-registry/opsmind:latest
2

Provision a PostgreSQL database

Any managed Postgres service works. Construct a DATABASE_URL connection string in the format postgresql://USER:PASSWORD@HOST:PORT/DB?schema=public.
3

Set environment variables on the platform

Configure DATABASE_URL, JWT_SECRET, and GEMINI_API_KEY as secrets or environment variables on your platform (Fly.io, Railway, AWS ECS, Kubernetes Secret, etc.).
4

Run the container

The startup CMD (npx prisma db push && npm start) will migrate the schema and start the server. Ensure the container has network access to the Postgres host.

CI pipeline

The GitHub Actions workflow at .github/workflows/ci.yml runs automatically on every push or pull request targeting the main or develop branches.
.github/workflows/ci.yml (key steps)
on:
  push:
    branches: ["main", "develop"]
  pull_request:
    branches: ["main", "develop"]

jobs:
  test:
    runs-on: ubuntu-latest
    env:
      DATABASE_URL: "postgresql://test_user:test_password@localhost:5432/monitor_test_db?schema=public"
      DIRECT_URL: "postgresql://test_user:test_password@localhost:5432/monitor_test_db?schema=public"
      JWT_SECRET: "super_secreto_para_entorno_de_pruebas"
      GEMINI_API_KEY: "test_dummy_key"
      PORT: "3000"
    services:
      postgres:
        image: postgres:15
        # ...health check options
The pipeline steps are:
1

Spin up a Postgres 15 service container

GitHub Actions starts a postgres:15 service with test_user / test_password / monitor_test_db. A health check using pg_isready ensures the database is accepting connections before any other steps run.
2

Install dependencies

npm ci installs a clean, reproducible set of dependencies from package-lock.json.
3

Generate Prisma client

npx prisma generate compiles the Prisma client from the schema so that the test suite can import it.
4

Push schema to the test database

npx prisma db push creates all tables in the ephemeral Postgres container, giving Jest a fully-provisioned database to run against.
5

Run the test suite

npm test executes Jest. The GEMINI_API_KEY is set to "test_dummy_key" so that AI service calls are gracefully handled without a real API key.

Running tests

Run the full test suite locally with:
Terminal
npm test
Jest is configured with --detectOpenHandles to catch any async resources (database connections, cron timers) that are not properly cleaned up after tests. Generate a coverage report with:
Terminal
npm run test:coverage

Build docs developers (and LLMs) love