local-deep-research Docker & Self-Hosted Deployment

GitHub

~95% on SimpleQA (e.g. Qwen3.6-27B on a 3090). Supports all local and cloud LLMs (llama.cpp, Ollama, Google, ...). 10+ search engines - arXiv, PubMed, your...

RAW Compose
1. Pull Image (DOCKERHUB) docker pull learningcircuit/local-deep-research
2. Docker Run (1-Click Launch) docker run -d --name local-deep-research --restart always learningcircuit/local-deep-research:latest
3. Podman Run podman run -d --name local-deep-research --restart always learningcircuit/local-deep-research:latest
4. Skopeo Inspect (Zero-Pull Manifest) skopeo inspect docker://docker.io/learningcircuit/local-deep-research:latest
5. ORAS Pull (OCI Artifact) oras pull learningcircuit/local-deep-research:latest
6. Compose Deployment docker compose up -d
cookiecutter-docker/{{cookiecutter.config_name}}/docker-compose.{{cookiecutter.config_name}}.yml
Download .yml
services:
  local-deep-research:
    {%- if cookiecutter.build %}
    build:
      context: .
      dockerfile: Dockerfile
      target: ldr
    {% else %}
    image: localdeepresearch/local-deep-research
    {% endif %}
    {%- if cookiecutter.host_network %}
    network_mode: host  # Best option for connecting to locally running Ollama
    {% else %}
    networks:
      - ldr-network
    {% endif %}
    ports:
      - "{{cookiecutter.host_port}}:{{cookiecutter.host_port}}"
    environment:
      # Web Interface Settings
      - LDR_WEB_PORT={{cookiecutter.host_port}}
      - LDR_WEB_HOST={{cookiecutter.host_ip}}
      {%- if cookiecutter._enable_ollama %}
      - LDR_LLM_PROVIDER=ollama
      - LDR_LLM_OLLAMA_URL=http://ollama:11434
      {% endif %}
      {%- if cookiecutter.enable_searxng %}
      - LDR_SEARCH_ENGINE_WEB_SEARXNG_DEFAULT_PARAMS_INSTANCE_URL=http://searxng:8080
      {% endif %}
      # Data directory configuration
      - LDR_DATA_DIR=/data
    volumes:
      - ldr_data:/data
      - ldr_scripts:/scripts
      # Local document collections are managed via the Collections UI,
      # not via Docker volume mounts. Do not add local_collections mounts here.
    # Security: drop all capabilities, add back only what the entrypoint needs
    security_opt:
      - "no-new-privileges:true"
    cap_drop:
      - ALL
    cap_add:
      - CHOWN        # chown -R ldruser:ldruser /data
      - FOWNER       # chmod on files not owned by root
      - DAC_OVERRIDE # mkdir in /home/ldruser (.config dir)
      - SETUID       # setpriv setuid() to switch to ldruser
      - SETGID       # setpriv setgid() to switch group
    restart: unless-stopped
    {%- if cookiecutter._enable_ollama or cookiecutter.enable_searxng %}
    depends_on:
      {%- if cookiecutter._enable_ollama %}
      ollama:
        condition: service_healthy
      {% endif %}
      {%- if cookiecutter.enable_searxng %}
      searxng:
        condition: service_started
      {% endif %}
    {% endif %}

  {%- if cookiecutter._enable_ollama %}
  ollama:
    {%- if cookiecutter.enable_gpu and cookiecutter._amd_gpu %}
    image: ollama/ollama:rocm
    {% else %}
    image: ollama/ollama:latest
    {% endif %}
    container_name: ollama_service
    entrypoint: "/scripts/ollama_entrypoint.sh ${MODEL:-{{ cookiecutter._ollama_model }}}"
    healthcheck:
      test: [ "CMD", "ollama", "show", "${MODEL:-{{ cookiecutter._ollama_model }}}" ]
      interval: 10s
      timeout: 5s
      start_period: 10m
      retries: 2
    environment:
      OLLAMA_KEEP_ALIVE: '30m'
    volumes:
      - ollama_data:/root/.ollama
      - ldr_scripts:/scripts
    {%- if not cookiecutter.host_network %}
    networks:
      - ldr-network
    {% endif %}
    {%- if cookiecutter.enable_gpu %}
    {%- if cookiecutter._nvidia_gpu %}
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    {% elif cookiecutter._amd_gpu %}
    devices:
      - "/dev/kfd:/dev/kfd"
      - "/dev/dri:/dev/dri"
    {% endif %}
    {% endif %}
    security_opt:
      - "no-new-privileges:true"
    restart: unless-stopped
  {% endif %}

  {%- if cookiecutter.enable_searxng %}
  searxng:
    image: searxng/searxng:latest
    container_name: searxng
    {%- if not cookiecutter.host_network %}
    networks:
      - ldr-network
    {% endif %}
    volumes:
      - searxng_data:/etc/searxng
    restart: unless-stopped
  {% endif %}

volumes:
  ldr_data:
  ldr_scripts:
  ollama_data:
  searxng_data:

{%- if not cookiecutter.host_network %}
networks:
  ldr-network:
{% endif %}