From 4eb9d7fb37a8d79e8b33384a8e98e019d6679036 Mon Sep 17 00:00:00 2001 From: nfel Date: Sun, 2 Aug 2026 23:33:59 +0330 Subject: [PATCH] feat: docker and docker compose added --- .dockerignore | 15 +++++++++++++++ .env.example | 3 +++ Dockerfile | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 21 +++++++++++++++++++++ compose.yaml | 15 +++++++++++++++ 5 files changed, 103 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 compose.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ff731e4 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +.git +.agents +.codex +.env +.resume-agent +.venv +.pytest_cache +.ruff_cache +output +**/__pycache__ +**/*.py[cod] +vendor/oh-my-cv/node_modules +vendor/oh-my-cv/site/.nuxt +vendor/oh-my-cv/site/.output +vendor/oh-my-cv/packages/*/dist diff --git a/.env.example b/.env.example index 4079715..10b32a3 100644 --- a/.env.example +++ b/.env.example @@ -6,3 +6,6 @@ RESUME_AGENT_API_STYLE=chat RESUME_AGENT_LLM_TIMEOUT_SECONDS=1800 RESUME_AGENT_LOG_LEVEL=INFO RESUME_AGENT_LOG_MODEL_PAYLOADS=true + +# Optional host port used by Docker Compose. +RESUME_AGENT_PORT=8000 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f5a9650 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,49 @@ +FROM node:20-bookworm-slim AS editor-builder + +WORKDIR /build/vendor/oh-my-cv + +RUN corepack enable +RUN corepack prepare pnpm@9.4.0 --activate + +COPY vendor/oh-my-cv/ ./ + +RUN pnpm install --frozen-lockfile --registry=https://registry.npmjs.org + +ENV NUXT_PUBLIC_SIGNAL_API_BASE="" + +RUN pnpm build-fast:pkg +RUN pnpm build + + +FROM python:3.12-slim AS runtime + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + PIP_DISABLE_PIP_VERSION_CHECK=1 \ + PIP_DEFAULT_TIMEOUT=120 \ + PIP_RETRIES=5 \ + PYTHONPATH=/app/src + +WORKDIR /app + +COPY pyproject.toml README.md ./ +COPY src/ ./src/ + +RUN pip install --no-cache-dir . + +COPY --from=editor-builder /build/vendor/oh-my-cv/site/.output/public/ \ + ./vendor/oh-my-cv/site/.output/public/ + +RUN groupadd --gid 1000 resume-agent \ + && useradd --uid 1000 --gid resume-agent --create-home resume-agent \ + && mkdir -p /app/.resume-agent /app/output \ + && chown -R resume-agent:resume-agent /app + +USER resume-agent + +EXPOSE 8000 + +HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=5 \ + CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/api/status', timeout=5).read()"] + +CMD ["uvicorn", "resume_agent.webapp:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/README.md b/README.md index 6389293..6f845e3 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,27 @@ bundled Oh My CV Markdown editor. Its **AI Tailor with Signal** tool can learn t current editor buffer, tailor it to a job URL or pasted description, apply the audited Markdown directly, and restore the pre-AI version with one click. +### Docker Compose + +After configuring `.env`, build and start the complete app with: + +```bash +docker compose up --build +``` + +Open `http://127.0.0.1:8000`. The image builds Oh My CV and serves it from `/cv/` through +the same FastAPI process. Career-profile state and generated resumes persist in the +host's `.resume-agent/` and `output/` directories. + +To use another host port, set `RESUME_AGENT_PORT` when starting Compose: + +```bash +RESUME_AGENT_PORT=8080 docker compose up --build +``` + +Stop the service with `docker compose down`. This leaves the persisted profile and +outputs intact. + Both frontends include a **Tailoring strength** slider. At `0`, the agent stays close to the source wording and organization. At `100`, it uses the fullest supported detail and strongest truthful job alignment. The slider never relaxes evidence validation; diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..5cbefd5 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,15 @@ +services: + resume-agent: + build: + context: . + dockerfile: Dockerfile + image: resume-agent:local + init: true + env_file: + - .env + ports: + - "${RESUME_AGENT_PORT:-8000}:8000" + volumes: + - ./.resume-agent:/app/.resume-agent + - ./output:/app/output + restart: unless-stopped