phase: 01-docker-compose-stack
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- requirements.txt
- Dockerfile
- .env.example
autonomous: true
requirements:
- SVC-01
- SVC-02
- SVC-05
must_haves:
truths:
- "requirements.txt declares psycopg2-binary matching code imports"
- "Dockerfile builds successfully with python:3.14-slim"
- ".env.example contains container service hostnames (db, ollama) not localhost"
artifacts:
- path: "requirements.txt"
provides: "Fixed Python dependencies with psycopg2-binary and upgraded pgvector"
contains: "psycopg2-binary"
- path: "Dockerfile"
provides: "Python app container image definition"
contains: "FROM python:3.14-slim"
- path: ".env.example"
provides: "Environment variable template with container hostnames"
contains: "db:5432"
key_links:
- from: "Dockerfile"
to: "requirements.txt"
via: "COPY + pip install"
pattern: "COPY requirements.txt"
Fix the psycopg2/psycopg3 dependency mismatch in requirements.txt, create a Dockerfile for the FastAPI app, and update .env.example with Docker container hostnames.
Purpose: Establishes the build foundation -- without correct dependencies the container will crash on import, and without container hostnames the services cannot communicate.
Output: requirements.txt (fixed), Dockerfile (new), .env.example (updated)
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/01-docker-compose-stack/01-RESEARCH.md
@requirements.txt
@api.py
@ingest.py
@query.py
@.env.example
- requirements.txt (current broken state: has psycopg[binary]>=3.1 but code imports psycopg2)
- ingest.py (line 15: import psycopg2; line 17: from pgvector.psycopg2 import register_vector)
- query.py (line 15: import psycopg2; line 17: from pgvector.psycopg2 import register_vector)
Replace the contents of requirements.txt with the following pinned dependencies:
```
fastapi==0.111.0
uvicorn[standard]==0.29.0
psycopg2-binary==2.9.11
pgvector==0.4.2
httpx==0.27.0
anthropic==0.25.0
python-dotenv==1.0.1
python-multipart==0.0.9
```
Changes from current file:
- REMOVE `psycopg[binary]>=3.1` (psycopg3 -- code does NOT use psycopg3 API)
- ADD `psycopg2-binary==2.9.11` (code does `import psycopg2` and `from pgvector.psycopg2`)
- CHANGE `pgvector==0.2.5` to `pgvector==0.4.2` (upgrade; supports both psycopg2 and psycopg3)
- All other lines remain identical
- requirements.txt contains psycopg2-binary==2.9.11
- requirements.txt contains pgvector==0.4.2
- requirements.txt does NOT contain psycopg[binary]
- requirements.txt still contains fastapi==0.111.0, uvicorn[standard]==0.29.0, httpx==0.27.0, anthropic==0.25.0, python-dotenv==1.0.1, python-multipart==0.0.9
- requirements.txt (after Task 1 fix -- to confirm psycopg2-binary is present)
- api.py (entrypoint: uvicorn api:app, port 8080, mounts /public)
- .planning/phases/01-docker-compose-stack/01-RESEARCH.md (Dockerfile pattern in "Code Examples" section)
Create a new file Dockerfile in the repo root with the following exact content:
```dockerfile
FROM python:3.14-slim
WORKDIR /app
# System dependency for psycopg2-binary
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8080"]
```
Key decisions:
- python:3.14-slim: matches local dev version, multi-arch (ARM64+AMD64)
- libpq5: runtime dependency for psycopg2-binary (not libpq-dev -- we use binary wheel)
- WORKDIR /app: all app files copied here, logs/ will be bind-mounted at /app/logs
- Port 8080: matches existing api.py startup command
- COPY . .: copies api.py, ingest.py, query.py, public/, schema.sql into image
- Dockerfile exists in repo root
- Dockerfile contains FROM python:3.14-slim
- Dockerfile contains WORKDIR /app
- Dockerfile contains RUN apt-get update && apt-get install -y --no-install-recommends with libpq5
- Dockerfile contains COPY requirements.txt . followed by RUN pip install --no-cache-dir -r requirements.txt
- Dockerfile contains COPY . .
- Dockerfile contains EXPOSE 8080
- Dockerfile contains CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8080"]
- .env.example (current: uses localhost for DATABASE_URL and OLLAMA_URL)
- .planning/phases/01-docker-compose-stack/01-RESEARCH.md (Pattern 5: Environment Variable Connection Strings)
- ingest.py (reads DATABASE_URL, OLLAMA_URL from env)
- query.py (reads DATABASE_URL, OLLAMA_URL, ANTHROPIC_API_KEY from env)
Replace the contents of .env.example with:
```
# RAG Support Desk – Docker Compose
# Kopiere nach .env und setze ANTHROPIC_API_KEY.
# App-Konfiguration (von api.py, ingest.py, query.py gelesen)
DATABASE_URL=postgresql://rag:rag@db:5432/supportdesk
OLLAMA_URL=http://ollama:11434
ANTHROPIC_API_KEY=sk-ant-...
# PostgreSQL-Container-Konfiguration (von db-Service gelesen)
POSTGRES_USER=rag
POSTGRES_PASSWORD=rag
POSTGRES_DB=supportdesk
```
Changes from current:
- DATABASE_URL: `localhost:5432` changed to `db:5432` (Docker service name)
- DATABASE_URL: `user:password` changed to `rag:rag` (matching POSTGRES_USER/PASSWORD)
- OLLAMA_URL: `localhost:11434` changed to `ollama:11434` (Docker service name)
- ADDED: POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB (used by pgvector/pgvector:pg17 container)
- ADDED: German-language comments explaining the sections
- .env.example contains DATABASE_URL=postgresql://rag:rag@db:5432/supportdesk
- .env.example contains OLLAMA_URL=http://ollama:11434
- .env.example contains ANTHROPIC_API_KEY=sk-ant-...
- .env.example contains POSTGRES_USER=rag
- .env.example contains POSTGRES_PASSWORD=rag
- .env.example contains POSTGRES_DB=supportdesk
- .env.example does NOT contain localhost
All three files exist and contain the correct values:
- grep "psycopg2-binary" requirements.txt returns a match
- grep "FROM python:3.14-slim" Dockerfile returns a match
- grep "db:5432" .env.example returns a match
- No localhost in .env.example
- No psycopg[binary] in requirements.txt
- requirements.txt has psycopg2-binary==2.9.11 (not psycopg3), pgvector==0.4.2
- Dockerfile builds with python:3.14-slim, installs deps, exposes 8080
- .env.example has container hostnames (db:5432, ollama:11434) and POSTGRES_* vars