diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..fb39adcd --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +.git +.venv/ +venv/ +**/.venv/ +**/venv/ +node_modules/ +**/node_modules/ +__pycache__/ +**/__pycache__/ +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +catboost_info/ +data_files/f1_cache/ +**/f1_cache/ diff --git a/fastapi_react/backend/Dockerfile b/fastapi_react/backend/Dockerfile index 7e86be3a..48d04fda 100644 --- a/fastapi_react/backend/Dockerfile +++ b/fastapi_react/backend/Dockerfile @@ -10,11 +10,11 @@ ENV PYTHONDONTWRITEBYTECODE=1 \ RUN apt-get update && apt-get install -y --no-install-recommends libgomp1 && rm -rf /var/lib/apt/lists/* -WORKDIR /app +WORKDIR /app/fastapi_react/backend COPY fastapi_react/backend/requirements.txt /tmp/requirements.txt RUN pip install --no-cache-dir -r /tmp/requirements.txt -COPY fastapi_react/backend/app /app/app +COPY fastapi_react/backend/app /app/fastapi_react/backend/app EXPOSE 8000 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"] diff --git a/fastapi_react/docker-compose.prod.yml b/fastapi_react/docker-compose.prod.yml new file mode 100644 index 00000000..3eaaca54 --- /dev/null +++ b/fastapi_react/docker-compose.prod.yml @@ -0,0 +1,19 @@ +services: + backend: + build: + context: .. + dockerfile: fastapi_react/backend/Dockerfile + environment: + F1_REPO_ROOT: /repo + F1_TRUSTED_LOCAL: "0" + ENABLE_EXPENSIVE_TOOLS: "0" + OMP_NUM_THREADS: "1" + OPENBLAS_NUM_THREADS: "1" + MKL_NUM_THREADS: "1" + NUMEXPR_NUM_THREADS: "1" + volumes: + - ..:/repo:ro + ports: + - "127.0.0.1:8000:8000" + restart: unless-stopped + mem_limit: 1600m diff --git a/fastapi_react/frontend/functions/api/[[path]].js b/fastapi_react/frontend/functions/api/[[path]].js new file mode 100644 index 00000000..d30e4ee2 --- /dev/null +++ b/fastapi_react/frontend/functions/api/[[path]].js @@ -0,0 +1,29 @@ +export async function onRequest({ request, env }) { + if (!env.F1_API_ORIGIN) { + return new Response("API origin is not configured", { status: 503 }); + } + + let apiUrl; + try { + apiUrl = new URL(env.F1_API_ORIGIN); + } catch { + return new Response("API origin is invalid", { status: 500 }); + } + + if ( + apiUrl.protocol !== "https:" || + apiUrl.pathname !== "/" || + apiUrl.search || + apiUrl.hash || + apiUrl.username || + apiUrl.password + ) { + return new Response("API origin must be an HTTPS origin", { status: 500 }); + } + + const incomingUrl = new URL(request.url); + apiUrl.pathname = incomingUrl.pathname; + apiUrl.search = incomingUrl.search; + + return fetch(new Request(apiUrl, request)); +}