# syntax=docker/dockerfile:1 # # Backend image. The FastAPI API and all four Taskiq processes (inbox worker and # scheduler, CV worker and scheduler) run from this one image; docker-compose picks # the process with `command:`. # # THE BUILD CONTEXT IS THE REPO ROOT, not ./backend: # # docker build -f backend/Dockerfile -t hrms-backend:local . # # backend/job/candidate imports the bulk-ats scoring engine (`app.core.errors`, # `app.services.pdf`, `app.services.scoring`), which lives in app/ at the repo root # and is pulled in transitively by inbox.plugins -> inbox.tasks. A ./backend context # cannot see it, so the workers would die on import. FROM python:3.12-slim ENV PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ PIP_NO_CACHE_DIR=1 \ PYTHONPATH=/app WORKDIR /app COPY backend/requirements.txt ./requirements.txt RUN pip install --no-cache-dir -r requirements.txt # Backend tree at /app; the scoring engine at /app/app so `import app.services.pdf` # resolves under PYTHONPATH=/app. requirements.txt says to `pip install -e ..` for # this in a host environment — copying it in is the container equivalent, and its # dependencies (openai, pypdf, pydantic-settings, python-multipart) are already pinned # above. COPY backend/ /app/ COPY app/ /app/app/ # Decoded CV attachments are read and written here. docker-compose bind-mounts the # host folder over this path so every container shares one set of files; creating it # in the image keeps an un-mounted container from failing on first write. RUN mkdir -p /app/inbox/decoded_attachments EXPOSE 8000 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]