Update CLAUDE.md with Dokploy deployment docs and fixes
Some checks are pending
CI / Engine — lint / typecheck / test (push) Waiting to run
CI / API — lint / typecheck / test (push) Waiting to run
CI / Web — typecheck / lint / build (push) Waiting to run

This commit is contained in:
Manohar Gupta 2026-05-15 09:45:37 +05:30
parent 79701c5e93
commit b184d74ad4

188
CLAUDE.md
View file

@ -78,3 +78,191 @@ Key modules (read in this order for domain understanding):
- **workers/** — Arq async tasks (run via Redis queue) - **workers/** — Arq async tasks (run via Redis queue)
- **db/** — SQLAlchemy models + migrations - **db/** — SQLAlchemy models + migrations
- **main.py** — FastAPI app factory - **main.py** — FastAPI app factory
## Deployment (Dokploy)
### Docker Configuration
**API Dockerfile** (`packages/api/Dockerfile`):
```dockerfile
FROM python:3.12-slim
WORKDIR /app
RUN pip install poetry
COPY packages /app/packages
WORKDIR /app/packages/api
RUN poetry install --no-interaction
ENV VENV_PATH=/root/.cache/pypoetry/virtualenvs/remodel-api-cufy8KWC-py3.12/bin
ENV PATH=$VENV_PATH:$PATH
ENV PYTHONPATH=/app/packages/engine/src:/app/packages/api/src
WORKDIR /app/packages/api
EXPOSE 8000
CMD ["uvicorn", "remodel_api.main:app", "--host", "0.0.0.0", "--port", "8000"]
```
**Web Dockerfile** (`packages/web/Dockerfile`):
```dockerfile
FROM node:22-alpine AS builder
WORKDIR /app
RUN corepack enable && corepack prepare pnpm@latest --activate
COPY package.json pnpm-lock.yaml ./
COPY . .
RUN test -f .env.local || echo "# placeholder" > .env.local
RUN pnpm install --frozen-lockfile --ignore-scripts
RUN pnpm build
FROM node:22-alpine
WORKDIR /app
RUN corepack enable && corepack prepare pnpm@latest --activate
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json .
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/.env.local ./.env.local
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
EXPOSE 3000
CMD ["/app/node_modules/.bin/next", "start"]
```
### docker-compose.yml (Dokploy)
```yaml
services:
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis_data:/data
networks:
- internal
api:
build:
context: .
dockerfile: packages/api/Dockerfile
restart: unless-stopped
environment:
- DATABASE_URL=sqlite+aiosqlite:///./remodel.db
- REDIS_URL=redis://redis:6379
depends_on:
- redis
labels:
- "traefik.enable=true"
- "traefik.docker.network=web"
- "traefik.http.routers.api.rule=Host(`model.manohargupta.com`) && PathPrefix(`/api`)"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=letsencrypt"
- "traefik.http.services.api.loadbalancer.server.port=8000"
networks:
- internal
- web
worker:
build:
context: .
dockerfile: packages/api/Dockerfile
command: python -m arq remodel_api.workers.main.WorkerSettings
restart: unless-stopped
environment:
- DATABASE_URL=sqlite+aiosqlite:///./remodel.db
- REDIS_URL=redis://redis:6379
depends_on:
- redis
networks:
- internal
web:
build:
context: ./packages/web
dockerfile: Dockerfile
restart: unless-stopped
environment:
- NEXT_PUBLIC_API_URL=https://model.manohargupta.com/api
labels:
- "traefik.enable=true"
- "traefik.docker.network=web"
- "traefik.http.routers.web.rule=Host(`model.manohargupta.com`)"
- "traefik.http.routers.web.entrypoints=websecure"
- "traefik.http.routers.web.tls.certresolver=letsencrypt"
- "traefik.http.services.web.loadbalancer.server.port=3000"
networks:
- web
networks:
internal:
internal: true
web:
name: dokploy-network
external: true
volumes:
redis_data:
```
### Environment Variables
| Variable | Description | Required |
|----------|-------------|----------|
| `DATABASE_URL` | SQLite with async driver | `sqlite+aiosqlite:///./remodel.db` |
| `REDIS_URL` | Redis connection string | `redis://redis:6379` |
| `NEXT_PUBLIC_API_URL` | Public API URL for web | `https://model.manohargupta.com/api` |
### CORS Configuration
In `packages/api/src/remodel_api/main.py`:
```python
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000", "https://model.manohargupta.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
```
### Config Settings
In `packages/api/src/remodel_api/config.py`:
```python
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_prefix="", extra="ignore")
database_url: str = "sqlite+aiosqlite:///./remodel.db"
redis_url: str = "redis://localhost:6379"
```
**Important**: No prefix for env vars - they must match docker-compose exactly.
### Network Requirements
- `dokploy-network` must exist on Dokploy server (external network)
- Traefik uses `websecure` endpoint (HTTPS with Let's Encrypt TLS)
## Deployment Issues & Fixes
| Issue | Cause | Fix |
|-------|-------|-----|
| Poetry pyproject.toml not found | COPY syntax wrong in Dockerfile | Copy entire `packages/` directory |
| `--no-venv-seeding` flag error | Old Poetry version | Remove the flag |
| Missing `.env.local` | Not in git | Create placeholder in builder stage |
| `uvicorn` not in PATH | Poetry venv not in PATH | Set `ENV PATH=$VENV_PATH:$PATH` |
| `next` not found | pnpm stores bins differently | Use absolute path `/app/node_modules/.bin/next` |
| 504 Gateway Timeout | Redis/DB not accessible | Check network, restart containers |
| Worker can't connect to Redis | Wrong env prefix | Use `REDIS_URL` not `REMODEL_REDIS_URL` |
| SQLite async error | Wrong driver | Use `sqlite+aiosqlite://` not `sqlite://` |
| CORS blocked | Origin mismatch | Add production domain to allow_origins |