Merge pull request #205 from ggozad/fix/docker-paths
Clarify how folder mounts work in docker docs
This commit is contained in:
commit
30f6bac388
6 changed files with 105 additions and 8 deletions
|
|
@ -1,6 +1,15 @@
|
|||
# Changelog
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- **File Monitor Path Validation**: Monitor now validates directories exist before watching ([#204](https://github.com/ggozad/haiku.rag/issues/204))
|
||||
- Provides clear error message pointing to `haiku.rag.yaml` configuration
|
||||
- Prevents cryptic `FileNotFoundError: No path was found` from watchfiles
|
||||
- **Docker Documentation**: Improved Docker setup instructions
|
||||
- Added volume mount examples for config file and documents directory
|
||||
- Clarified that `monitor.directories` must use container paths, not host paths
|
||||
|
||||
## [0.21.0] - 2025-12-18
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -44,19 +44,35 @@ Mount your config file and data directory:
|
|||
|
||||
```bash
|
||||
docker run -p 8001:8001 \
|
||||
-v $(pwd)/haiku.rag.yaml:/app/haiku.rag.yaml \
|
||||
-v $(pwd)/data:/data \
|
||||
-v /path/to/haiku.rag.yaml:/app/haiku.rag.yaml \
|
||||
-v /path/to/data:/data \
|
||||
haiku-rag
|
||||
```
|
||||
|
||||
The container will automatically use the mounted `haiku.rag.yaml` configuration file.
|
||||
To enable file monitoring, also mount a documents directory:
|
||||
|
||||
```bash
|
||||
docker run -p 8001:8001 \
|
||||
-v /path/to/haiku.rag.yaml:/app/haiku.rag.yaml \
|
||||
-v /path/to/data:/data \
|
||||
-v /path/to/docs:/docs \
|
||||
haiku-rag haiku-rag serve --mcp --monitor
|
||||
```
|
||||
|
||||
Your `haiku.rag.yaml` must reference the **container path** for monitoring:
|
||||
|
||||
```yaml
|
||||
monitor:
|
||||
directories:
|
||||
- /docs # Container path, not host path
|
||||
```
|
||||
|
||||
For API keys (OpenAI, Anthropic, etc.), pass them as environment variables:
|
||||
|
||||
```bash
|
||||
docker run -p 8001:8001 \
|
||||
-v $(pwd)/haiku.rag.yaml:/app/haiku.rag.yaml \
|
||||
-v $(pwd)/data:/data \
|
||||
-v /path/to/haiku.rag.yaml:/app/haiku.rag.yaml \
|
||||
-v /path/to/data:/data \
|
||||
-e OPENAI_API_KEY=your-key-here \
|
||||
haiku-rag
|
||||
```
|
||||
|
|
|
|||
|
|
@ -93,7 +93,10 @@ Build locally to include all features and document processing without docling-se
|
|||
|
||||
```bash
|
||||
docker build -f docker/Dockerfile -t haiku-rag .
|
||||
docker run -p 8001:8001 -v $(pwd)/data:/data haiku-rag
|
||||
docker run -p 8001:8001 \
|
||||
-v /path/to/haiku.rag.yaml:/app/haiku.rag.yaml \
|
||||
-v /path/to/data:/data \
|
||||
haiku-rag
|
||||
```
|
||||
|
||||
See `docker/README.md` for complete build and configuration instructions.
|
||||
See `docker/README.md` for complete build and configuration instructions, including how to enable file monitoring.
|
||||
|
|
|
|||
|
|
@ -14,13 +14,36 @@ This setup showcases the minimal haiku.rag-slim image combined with external doc
|
|||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Create required directories
|
||||
mkdir -p data docs
|
||||
cp haiku.rag.yaml.example haiku.rag.yaml # Edit as needed
|
||||
|
||||
# Create config file from example (required)
|
||||
cp haiku.rag.yaml.example haiku.rag.yaml
|
||||
|
||||
# Start services
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Place documents in `docs/` for automatic indexing.
|
||||
|
||||
## Volume Mounts
|
||||
|
||||
The docker-compose.yml mounts three volumes:
|
||||
|
||||
| Host Path | Container Path | Purpose |
|
||||
|-----------|---------------|---------|
|
||||
| `./data` | `/data` | Persistent LanceDB database |
|
||||
| `./docs` | `/docs` | Documents to monitor and index |
|
||||
| `./haiku.rag.yaml` | `/app/haiku.rag.yaml` | Configuration file |
|
||||
|
||||
**Important:** The `haiku.rag.yaml` config file must exist before running `docker compose up`. Copy it from the example:
|
||||
|
||||
```bash
|
||||
cp haiku.rag.yaml.example haiku.rag.yaml
|
||||
```
|
||||
|
||||
The example config sets `monitor.directories: [/docs]` - this is the **container path**, not your host path. Documents placed in `./docs` on your host will appear at `/docs` inside the container.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -90,6 +90,18 @@ class FileWatcher:
|
|||
self.supported_extensions = get_converter(config).supported_extensions
|
||||
|
||||
async def observe(self):
|
||||
if not self.paths:
|
||||
logger.warning("No directories configured for monitoring")
|
||||
return
|
||||
|
||||
# Validate all paths exist before attempting to watch
|
||||
missing_paths = [p for p in self.paths if not Path(p).exists()]
|
||||
if missing_paths:
|
||||
raise FileNotFoundError(
|
||||
f"Monitor directories do not exist: {missing_paths}. "
|
||||
"Check your haiku.rag.yaml configuration."
|
||||
)
|
||||
|
||||
logger.info(f"Watching files in {self.paths}")
|
||||
filter = FileFilter(
|
||||
ignore_patterns=self.ignore_patterns,
|
||||
|
|
|
|||
|
|
@ -440,3 +440,37 @@ async def test_file_watcher_orphan_handles_spaces_in_filenames():
|
|||
|
||||
# Should NOT delete the document since file exists
|
||||
mock_client.delete_document.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_file_watcher_observe_raises_on_missing_paths():
|
||||
"""Test observe() raises FileNotFoundError when directories don't exist."""
|
||||
mock_client = AsyncMock(spec=HaikuRAG)
|
||||
|
||||
test_config = AppConfig(
|
||||
monitor=MonitorConfig(
|
||||
directories=[Path("/nonexistent/path/that/does/not/exist")]
|
||||
)
|
||||
)
|
||||
watcher = FileWatcher(client=mock_client, config=test_config)
|
||||
|
||||
with pytest.raises(FileNotFoundError) as exc_info:
|
||||
await watcher.observe()
|
||||
|
||||
assert "Monitor directories do not exist" in str(exc_info.value)
|
||||
assert "haiku.rag.yaml" in str(exc_info.value)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_file_watcher_observe_returns_early_when_no_directories():
|
||||
"""Test observe() returns early when no directories are configured."""
|
||||
mock_client = AsyncMock(spec=HaikuRAG)
|
||||
|
||||
test_config = AppConfig(monitor=MonitorConfig(directories=[]))
|
||||
watcher = FileWatcher(client=mock_client, config=test_config)
|
||||
|
||||
# Should return without error when no directories configured
|
||||
await watcher.observe()
|
||||
|
||||
# No documents should have been processed
|
||||
mock_client.create_document_from_source.assert_not_called()
|
||||
|
|
|
|||
Loading…
Reference in a new issue