prowler Docker & Self-Hosted Deployment

GitHub

This repo hosts Prowler OSS (CLI and Local Server). Prowler is the world’s most widely used open-source cloud security platform that automates security and...

15,087 stars Python Python 1 file Β· ~270,749 tokens #aws#azure#cis-benchmark#cloud#cloudsecurity#compliance#cspm#devsecops
RAW Compose
1. Pull Image (DOCKERHUB) docker pull library/postgres
2. Docker Run (1-Click Launch) docker run -d --name prowler -p 3000:3000 --restart always postgres:16-alpine@sha256:57c72fd2a128e416c7fcc499958864df5301e940bca0a56f58fddf30ffc07777
3. Podman Run podman run -d --name prowler -p 3000:3000 --restart always postgres:16-alpine@sha256:57c72fd2a128e416c7fcc499958864df5301e940bca0a56f58fddf30ffc07777
4. Skopeo Inspect (Zero-Pull Manifest) skopeo inspect docker://docker.io/library/postgres:16-alpine@sha256
5. ORAS Pull (OCI Artifact) oras pull postgres:16-alpine@sha256:57c72fd2a128e416c7fcc499958864df5301e940bca0a56f58fddf30ffc07777
6. Compose Deployment docker compose up -d
docker-compose.yml
Download .yml
# Production Docker Compose configuration
# Uses pre-built images from Docker Hub (prowlercloud/*)
#
# For development with local builds and hot-reload, use docker-compose-dev.yml instead:
#   docker compose -f docker-compose-dev.yml up
#
services:
  api-init:
    image: busybox:1.37.0@sha256:9532d8c39891ca2ecde4d30d7710e01fb739c87a8b9299685c63704296b16028
    volumes:
      - ./_data/api:/data
    command: ["sh", "-c", "chown -R 1000:1000 /data"]
    restart: "no"

  api:
    hostname: "prowler-api"
    image: prowlercloud/prowler-api:${PROWLER_API_VERSION:-stable}
    restart: unless-stopped
    env_file:
      - path: .env
        required: false
    ports:
      - "${DJANGO_PORT:-8080}:${DJANGO_PORT:-8080}"
    volumes:
      - ./_data/api:/home/prowler/.config/prowler-api
      - output:/tmp/prowler_api_output
    depends_on:
      api-init:
        condition: service_completed_successfully
      postgres:
        condition: service_healthy
      valkey:
        condition: service_healthy
      neo4j:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:${DJANGO_PORT:-8080}/health/live || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 12
      start_period: 60s
    entrypoint:
      - "/home/prowler/docker-entrypoint.sh"
      - "prod"

  ui:
    image: prowlercloud/prowler-ui:${PROWLER_UI_VERSION:-stable}
    restart: unless-stopped
    env_file:
      - path: .env
        required: false
    ports:
      - ${UI_PORT:-3000}:3000
    depends_on:
      mcp-server:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:3000/api/health || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 60s

  postgres:
    image: postgres:16-alpine@sha256:57c72fd2a128e416c7fcc499958864df5301e940bca0a56f58fddf30ffc07777
    restart: unless-stopped
    hostname: "postgres-db"
    volumes:
      - ./_data/postgres:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=${POSTGRES_ADMIN_USER}
      - POSTGRES_PASSWORD=${POSTGRES_ADMIN_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB}
    env_file:
      - path: .env
        required: false
    ports:
      - "${POSTGRES_PORT:-5432}:${POSTGRES_PORT:-5432}"
    healthcheck:
      test: ["CMD-SHELL", "sh -c 'pg_isready -U ${POSTGRES_ADMIN_USER} -d ${POSTGRES_DB}'"]
      interval: 5s
      timeout: 5s
      retries: 5

  valkey:
    image: valkey/valkey:8-alpine@sha256:a038175878d66b9d274fbf8be73c0305e93798b83917647f167e18cef3c71eec
    restart: unless-stopped
    hostname: "valkey"
    volumes:
      - ./_data/valkey:/data
    env_file:
      - path: .env
        required: false
    ports:
      - "${VALKEY_PORT:-6379}:6379"
    healthcheck:
      test: ["CMD-SHELL", "sh -c 'valkey-cli ping'"]
      interval: 10s
      timeout: 5s
      retries: 3

  neo4j:
    image: graphstack/dozerdb:5.26.27.0@sha256:9b54d6b3a98a76c00bd23e8e78d8c82081ff168162aebd47b25c234e092cb0a0
    restart: unless-stopped
    hostname: "neo4j"
    volumes:
      - ./_data/neo4j:/data
    environment:
      # We can't add our .env file because some of our current variables are not compatible with Neo4j env vars
      # Auth
      - NEO4J_AUTH=${NEO4J_USER}/${NEO4J_PASSWORD}
      # Memory limits
      - NEO4J_dbms_max__databases=${NEO4J_DBMS_MAX__DATABASES:-1000}
      - NEO4J_server_memory_pagecache_size=${NEO4J_SERVER_MEMORY_PAGECACHE_SIZE:-1G}
      - NEO4J_server_memory_heap_initial__size=${NEO4J_SERVER_MEMORY_HEAP_INITIAL__SIZE:-1G}
      - NEO4J_server_memory_heap_max__size=${NEO4J_SERVER_MEMORY_HEAP_MAX__SIZE:-1G}
      # APOC
      - "NEO4J_PLUGINS=${NEO4J_PLUGINS:-[\"apoc\"]}"
      - "NEO4J_dbms_security_procedures_allowlist=${NEO4J_DBMS_SECURITY_PROCEDURES_ALLOWLIST:-apoc.*}"
      - "NEO4J_dbms_security_procedures_unrestricted=${NEO4J_DBMS_SECURITY_PROCEDURES_UNRESTRICTED:-}"
      - apoc.export.file.enabled=${NEO4J_APOC_EXPORT_FILE_ENABLED:-false}
      - apoc.import.file.enabled=${NEO4J_APOC_IMPORT_FILE_ENABLED:-false}
      - apoc.import.file.use_neo4j_config=${NEO4J_APOC_IMPORT_FILE_USE_NEO4J_CONFIG:-true}
      - apoc.trigger.enabled=${NEO4J_APOC_TRIGGER_ENABLED:-false}
      # Networking
      - "dbms.connector.bolt.listen_address=${NEO4J_DBMS_CONNECTOR_BOLT_LISTEN_ADDRESS:-0.0.0.0:7687}"
    ports:
      - ${NEO4J_PORT:-7687}:7687
    healthcheck:
        test: ["CMD", "wget", "--no-verbose", "http://localhost:7474"]
        interval: 10s
        timeout: 10s
        retries: 10

  worker:
    image: prowlercloud/prowler-api:${PROWLER_API_VERSION:-stable}
    restart: unless-stopped
    # Give Celery soft shutdown time to drain/re-queue in-flight tasks on stop.
    stop_grace_period: 120s
    env_file:
      - path: .env
        required: false
    volumes:
      - "output:/tmp/prowler_api_output"
    depends_on:
      api:
        condition: service_healthy
    ulimits:
      nofile:
        soft: 65536
        hard: 65536
    entrypoint:
      - "/home/prowler/docker-entrypoint.sh"
      - "worker"

  worker-beat:
    image: prowlercloud/prowler-api:${PROWLER_API_VERSION:-stable}
    restart: unless-stopped
    env_file:
      - path: ./.env
        required: false
    depends_on:
      api:
        condition: service_healthy
    ulimits:
      nofile:
        soft: 65536
        hard: 65536
    entrypoint:
      - "/home/prowler/docker-entrypoint.sh"
      - "beat"

  mcp-server:
    image: prowlercloud/prowler-mcp:${PROWLER_MCP_VERSION:-stable}
    restart: unless-stopped
    environment:
      - PROWLER_MCP_TRANSPORT_MODE=http
    env_file:
      - path: .env
        required: false
    ports:
      - "8000:8000"
    command: ["uvicorn", "--host", "0.0.0.0", "--port", "8000"]
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:8000/health || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 60s

volumes:
  output:
    driver: local