services: local-deep-research: # Allow request draining, then scheduler, queue, log and database cleanup. stop_grace_period: 60s {%- 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 - LDR_LLM_MODEL=${MODEL:-{{ cookiecutter._ollama_model }}} {% 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 # Use the image's own `ollama serve` entrypoint so a fresh data volume # can start independently of the LDR container. # After starting the stack, install the model selected during setup: # docker compose -f docker-compose.{{cookiecutter.config_name}}.yml exec ollama ollama pull {{ cookiecutter._ollama_model }} # If MODEL is overridden, pull that model instead. healthcheck: test: [ "CMD", "ollama", "list" ] interval: 10s timeout: 5s start_period: 30s retries: 5 environment: OLLAMA_KEEP_ALIVE: '30m' volumes: - ollama_data:/root/.ollama {%- 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 %}