From 264b26cb0a3bb2ae84fd6b371d125adc8e2069a4 Mon Sep 17 00:00:00 2001 From: extreme4all <> Date: Sat, 24 Jan 2026 16:46:33 +0100 Subject: [PATCH 1/5] ok --- docker-compose-debug.yml | 1 + ...compose-prod.yml => docker-compose-dev.yml | 55 ++++++------- docker-compose-oc.yml | 3 +- docker-compose.yml | 56 ++++++------- projects/api_ml/Dockerfile | 11 +-- projects/api_ml/Dockerfile.bak | 56 +++++++++++++ projects/api_public/Dockerfile | 7 +- projects/api_public/Dockerfile.bak | 57 +++++++++++++ projects/hiscore_scraper/Dockerfile | 75 ++++++++++++++--- projects/hiscore_scraper/Dockerfile.bak | 81 +++++++++++++++++++ projects/job_hs_migration_v3/Dockerfile | 53 ++++++++---- projects/job_hs_migration_v3/Dockerfile.bak | 30 +++++++ projects/job_prune_hs_data/Dockerfile | 53 ++++++++---- projects/job_prune_hs_data/Dockerfile.bak | 30 +++++++ projects/runemetrics_scraper/Dockerfile | 53 ++++++++---- projects/runemetrics_scraper/Dockerfile.bak | 30 +++++++ projects/scrape_task_producer/Dockerfile | 53 ++++++++---- projects/scrape_task_producer/Dockerfile.bak | 30 +++++++ projects/website/Dockerfile | 57 +++++++++---- projects/website/Dockerfile.bak | 30 +++++++ projects/worker_hiscore/Dockerfile | 53 ++++++++---- projects/worker_hiscore/Dockerfile.bak | 30 +++++++ projects/worker_ml/Dockerfile | 53 ++++++++---- projects/worker_ml/Dockerfile.bak | 30 +++++++ projects/worker_report/Dockerfile | 53 ++++++++---- projects/worker_report/Dockerfile.bak | 30 +++++++ 26 files changed, 869 insertions(+), 201 deletions(-) rename docker-compose-prod.yml => docker-compose-dev.yml (87%) create mode 100644 projects/api_ml/Dockerfile.bak create mode 100644 projects/api_public/Dockerfile.bak create mode 100644 projects/hiscore_scraper/Dockerfile.bak create mode 100644 projects/job_hs_migration_v3/Dockerfile.bak create mode 100644 projects/job_prune_hs_data/Dockerfile.bak create mode 100644 projects/runemetrics_scraper/Dockerfile.bak create mode 100644 projects/scrape_task_producer/Dockerfile.bak create mode 100644 projects/website/Dockerfile.bak create mode 100644 projects/worker_hiscore/Dockerfile.bak create mode 100644 projects/worker_ml/Dockerfile.bak create mode 100644 projects/worker_report/Dockerfile.bak diff --git a/docker-compose-debug.yml b/docker-compose-debug.yml index 8d44d9f..2554517 100644 --- a/docker-compose-debug.yml +++ b/docker-compose-debug.yml @@ -1,3 +1,4 @@ +# this docker-compose file is used for debugging and development purposes services: kafka: image: apache/kafka:3.7.2 diff --git a/docker-compose-prod.yml b/docker-compose-dev.yml similarity index 87% rename from docker-compose-prod.yml rename to docker-compose-dev.yml index 92c754b..7f1c508 100644 --- a/docker-compose-prod.yml +++ b/docker-compose-dev.yml @@ -1,3 +1,4 @@ +# this compose file is used for local development and testing services: # KAFKA kafka: @@ -96,6 +97,7 @@ services: # MINIO minio: image: minio/minio + container_name: minio expose: - "9000" - "9001" @@ -117,6 +119,7 @@ services: # Create a bucket named "bucket" if it doesn't exist minio-create-bucket: image: minio/mc + container_name: minio_create_bucket depends_on: minio: condition: service_healthy @@ -132,12 +135,12 @@ services: # COMPONENTS hiscore_scraper: container_name: hiscore_scraper - image: bd/hiscore_scraper # tags the image if build + image: bd/hiscore_scraper:dev build: context: ./ dockerfile: ./projects/hiscore_scraper/Dockerfile - target: production - # command: ["uv", "run", "uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning", "--reload", "--reload-dir", "/app/bot_detector/api_public/"] + target: dev + # command: ["sleep", "infinity"] networks: - botdetector-network env_file: @@ -149,11 +152,11 @@ services: condition: service_completed_successfully runemetrics_scraper: container_name: runemetrics_scraper - image: bd/runemetrics_scraper # tags the image if build + image: bd/runemetrics_scraper build: context: ./ dockerfile: ./projects/runemetrics_scraper/Dockerfile - target: production + target: dev # command: ["sleep", "infinity"] # command: ["uv", "run", "bot_detector/runemetrics_scraper/src/core.py"] networks: @@ -167,11 +170,11 @@ services: condition: service_completed_successfully worker_hiscore: container_name: worker_hiscore - image: bd/worker_hiscore # tags the image if build + image: bd/worker_hiscore build: context: ./ dockerfile: ./projects/worker_hiscore/Dockerfile - target: production + target: dev # command: ["sleep", "infinity"] # command: ["uv", "run", "bot_detector/worker_hiscore/src/core.py"] networks: @@ -191,11 +194,11 @@ services: condition: service_completed_successfully worker_report: container_name: worker_report - image: bd/worker_report # tags the image if build + image: bd/worker_report build: context: ./ dockerfile: ./projects/worker_report/Dockerfile - target: production + target: dev # command: ["sleep", "infinity"] networks: - botdetector-network @@ -210,11 +213,11 @@ services: condition: service_completed_successfully worker_ml: container_name: worker_ml - image: bd/worker_ml # tags the image if build + image: bd/worker_ml build: context: ./ dockerfile: ./projects/worker_ml/Dockerfile - target: production + target: dev # command: ["sleep", "infinity"] environment: - DATABASE_URL=mysql+asyncmy://ml-worker:ml_worker_pw@mysql:3306/playerdata @@ -237,11 +240,11 @@ services: scrape_task_producer: container_name: scrape_task_producer - image: bd/scrape_task_producer # tags the image if build + image: bd/scrape_task_producer build: context: ./ dockerfile: ./projects/scrape_task_producer/Dockerfile - target: production + target: dev # command: ["sleep", "infinity"] networks: - botdetector-network @@ -256,11 +259,11 @@ services: condition: service_completed_successfully job_prune_hs_data: container_name: job_prune_hs_data - image: bd/job_prune_hs_data # tags the image if build + image: bd/job_prune_hs_data build: context: ./ dockerfile: ./projects/job_prune_hs_data/Dockerfile - target: production + target: dev # command: ["sleep", "infinity"] networks: - botdetector-network @@ -276,11 +279,11 @@ services: condition: service_completed_successfully api_public: container_name: api_public - image: bd/api_public:prod + image: bd/api_public:dev build: context: . dockerfile: ./projects/api_public/Dockerfile - target: prod + target: dev # command: ["sleep", "infinity"] env_file: - .env @@ -291,8 +294,9 @@ services: - POOL_RECYCLE=60 - POOL_TIMEOUT=30 volumes: - - ./bases:/app/bases - - ./components:/app/components + - ./bases:/bases + - ./components:/components + # - uv_cache:/root/.cache/uv ports: - 5000 networks: @@ -323,6 +327,7 @@ services: build: context: . dockerfile: ./projects/website/Dockerfile + target: dev env_file: - .env environment: @@ -349,10 +354,8 @@ services: build: context: . dockerfile: ./projects/api_ml/Dockerfile - target: builder + target: dev # command: ["sleep", "infinity"] - command: > - sh -c "cd ../.. && projects/api_ml/.venv/bin/uvicorn bases.bot_detector.api_ml.core.server:app --host 0.0.0.0 --port 5000 --log-level warning --reload --reload-dir bases/bot_detector/api_ml" env_file: - .env environment: @@ -382,14 +385,6 @@ networks: botdetector-network: name: bd-network -# To create the docker volume for uv cache (run only once) -# docker volume create uv_cache - -# To copy existing cache from host to docker volume (run only once) -# docker run --rm \ -# -v uv_cache:/data \ -# -v ~/.cache/uv:/source \ -# alpine sh -c "cp -r /source/* /data/" volumes: uv_cache: external: true \ No newline at end of file diff --git a/docker-compose-oc.yml b/docker-compose-oc.yml index 32fc596..8dc30e2 100644 --- a/docker-compose-oc.yml +++ b/docker-compose-oc.yml @@ -27,8 +27,9 @@ services: - ./_mysql:/project/_mysql # configs and docs - ./docker-compose.yml:/project/docker-compose.yml - - ./docker-compose-dev.yml:/project/docker-compose-dev.yml - ./docker-compose-oc.yml:/project/docker-compose-oc.yml + - ./docker-compose-dev.yml:/project/docker-compose-dev.yml + - ./docker-compose-debug.yml:/project/docker-compose-debug.yml - ./README.md:/project/README.md env_file: - ./_opencode/.env diff --git a/docker-compose.yml b/docker-compose.yml index 56b85bb..4dca7d7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,3 +1,4 @@ +# this docker-compose file is used to simulate production environment services: # KAFKA kafka: @@ -96,7 +97,6 @@ services: # MINIO minio: image: minio/minio - container_name: minio expose: - "9000" - "9001" @@ -118,7 +118,6 @@ services: # Create a bucket named "bucket" if it doesn't exist minio-create-bucket: image: minio/mc - container_name: minio_create_bucket depends_on: minio: condition: service_healthy @@ -134,12 +133,12 @@ services: # COMPONENTS hiscore_scraper: container_name: hiscore_scraper - image: bd/hiscore_scraper # tags the image if build + image: bd/hiscore_scraper:prd build: context: ./ dockerfile: ./projects/hiscore_scraper/Dockerfile - target: production - # command: ["uv", "run", "uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning", "--reload", "--reload-dir", "/app/bot_detector/api_public/"] + target: prod + # command: ["sleep", "infinity"] networks: - botdetector-network env_file: @@ -151,11 +150,11 @@ services: condition: service_completed_successfully runemetrics_scraper: container_name: runemetrics_scraper - image: bd/runemetrics_scraper # tags the image if build + image: bd/runemetrics_scraper build: context: ./ dockerfile: ./projects/runemetrics_scraper/Dockerfile - target: production + target: prod # command: ["sleep", "infinity"] # command: ["uv", "run", "bot_detector/runemetrics_scraper/src/core.py"] networks: @@ -169,11 +168,11 @@ services: condition: service_completed_successfully worker_hiscore: container_name: worker_hiscore - image: bd/worker_hiscore # tags the image if build + image: bd/worker_hiscore build: context: ./ dockerfile: ./projects/worker_hiscore/Dockerfile - target: production + target: prod # command: ["sleep", "infinity"] # command: ["uv", "run", "bot_detector/worker_hiscore/src/core.py"] networks: @@ -193,11 +192,11 @@ services: condition: service_completed_successfully worker_report: container_name: worker_report - image: bd/worker_report # tags the image if build + image: bd/worker_report build: context: ./ dockerfile: ./projects/worker_report/Dockerfile - target: production + target: prod # command: ["sleep", "infinity"] networks: - botdetector-network @@ -212,11 +211,11 @@ services: condition: service_completed_successfully worker_ml: container_name: worker_ml - image: bd/worker_ml # tags the image if build + image: bd/worker_ml build: context: ./ dockerfile: ./projects/worker_ml/Dockerfile - target: production + target: prod # command: ["sleep", "infinity"] environment: - DATABASE_URL=mysql+asyncmy://ml-worker:ml_worker_pw@mysql:3306/playerdata @@ -236,14 +235,13 @@ services: condition: service_completed_successfully api_ml: condition: service_healthy - scrape_task_producer: container_name: scrape_task_producer - image: bd/scrape_task_producer # tags the image if build + image: bd/scrape_task_producer build: context: ./ dockerfile: ./projects/scrape_task_producer/Dockerfile - target: production + target: prod # command: ["sleep", "infinity"] networks: - botdetector-network @@ -258,11 +256,11 @@ services: condition: service_completed_successfully job_prune_hs_data: container_name: job_prune_hs_data - image: bd/job_prune_hs_data # tags the image if build + image: bd/job_prune_hs_data build: context: ./ dockerfile: ./projects/job_prune_hs_data/Dockerfile - target: production + target: prod # command: ["sleep", "infinity"] networks: - botdetector-network @@ -278,11 +276,11 @@ services: condition: service_completed_successfully api_public: container_name: api_public - image: bd/api_public:dev + image: bd/api_public:prod build: context: . dockerfile: ./projects/api_public/Dockerfile - target: dev + target: prod # command: ["sleep", "infinity"] env_file: - .env @@ -293,10 +291,9 @@ services: - POOL_RECYCLE=60 - POOL_TIMEOUT=30 volumes: - - ./bases:/bases - - ./components:/components - # - uv_cache:/root/.cache/uv - ports: + - ./bases:/app/bases + - ./components:/app/components + ports: - 5000 networks: - botdetector-network @@ -326,6 +323,7 @@ services: build: context: . dockerfile: ./projects/website/Dockerfile + target: prod env_file: - .env environment: @@ -352,7 +350,7 @@ services: build: context: . dockerfile: ./projects/api_ml/Dockerfile - target: dev + target: prod # command: ["sleep", "infinity"] env_file: - .env @@ -383,14 +381,6 @@ networks: botdetector-network: name: bd-network -# To create the docker volume for uv cache (run only once) -# docker volume create uv_cache - -# To copy existing cache from host to docker volume (run only once) -# docker run --rm \ -# -v uv_cache:/data \ -# -v ~/.cache/uv:/source \ -# alpine sh -c "cp -r /source/* /data/" volumes: uv_cache: external: true \ No newline at end of file diff --git a/projects/api_ml/Dockerfile b/projects/api_ml/Dockerfile index bf9e21e..e5a783e 100644 --- a/projects/api_ml/Dockerfile +++ b/projects/api_ml/Dockerfile @@ -7,7 +7,7 @@ ENV UV_COMPILE_BYTECODE=1 WORKDIR /app FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv /bin/ +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ WORKDIR /app @@ -19,12 +19,10 @@ RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ uv sync --frozen --no-dev --project ./projects/api_ml FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv uvx/ /bin/ +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ WORKDIR /app -COPY --from=builder /app/projects/api_ml/.venv /app/.venv - ENV PATH="/app/.venv/bin:$PATH" ENV PYTHONPATH="/app" @@ -32,9 +30,8 @@ COPY ./projects/api_ml ./projects/api_ml COPY ./bases ./bases COPY ./components ./components -# this installs dev dependencies RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --project ./projects/api_ml \ + uv sync --dev --project ./projects/api_ml \ && cp -r projects/api_ml/.venv/ .venv/ CMD ["uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] @@ -54,4 +51,4 @@ ENV PYTHONPATH="/app" USER appuser -CMD ["python3", "-m", "uvicorn", "bot_detector.api_ml.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] \ No newline at end of file +CMD ["python3", "-m", "uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] \ No newline at end of file diff --git a/projects/api_ml/Dockerfile.bak b/projects/api_ml/Dockerfile.bak new file mode 100644 index 0000000..6e1a4ed --- /dev/null +++ b/projects/api_ml/Dockerfile.bak @@ -0,0 +1,56 @@ +FROM python:3.12-slim-bookworm AS base + +# Python optimizations +ENV PYTHONUNBUFFERED=1 +ENV UV_COMPILE_BYTECODE=1 + +WORKDIR /app + +FROM base AS builder +COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv /bin/ + +WORKDIR /app + +COPY ./projects/api_ml ./projects/api_ml +COPY ./bases ./bases +COPY ./components ./components + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev --project ./projects/api_ml + +FROM base AS dev +COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv uvx/ /bin/ +COPY --from=builder /app/projects/api_ml/.venv /app/.venv + +WORKDIR /app + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +COPY ./projects/api_ml ./projects/api_ml +COPY ./bases ./bases +COPY ./components ./components + +# this installs dev dependencies +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --project ./projects/api_ml \ + && cp -r projects/api_ml/.venv/ .venv/ + +CMD ["uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] + +FROM base AS prod + +WORKDIR /app + +# Create a secure user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + +COPY --from=builder --chown=appuser /app/projects/api_ml/.venv /app/.venv + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +USER appuser + +CMD ["python3", "-m", "uvicorn", "bot_detector.api_ml.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] \ No newline at end of file diff --git a/projects/api_public/Dockerfile b/projects/api_public/Dockerfile index ece9e6b..7e2bac5 100644 --- a/projects/api_public/Dockerfile +++ b/projects/api_public/Dockerfile @@ -7,7 +7,7 @@ ENV UV_COMPILE_BYTECODE=1 WORKDIR /app FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv /bin/ +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ WORKDIR /app @@ -19,7 +19,7 @@ RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ uv sync --frozen --no-dev --project ./projects/api_public FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv uvx/ /bin/ +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ WORKDIR /app @@ -32,9 +32,8 @@ COPY ./projects/api_public ./projects/api_public COPY ./bases ./bases COPY ./components ./components -# this installs dev dependencies RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --project ./projects/api_public \ + uv sync --dev --project ./projects/api_public \ && cp -r projects/api_public/.venv/ .venv/ CMD ["uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] diff --git a/projects/api_public/Dockerfile.bak b/projects/api_public/Dockerfile.bak new file mode 100644 index 0000000..ece9e6b --- /dev/null +++ b/projects/api_public/Dockerfile.bak @@ -0,0 +1,57 @@ +FROM python:3.12-slim-bookworm AS base + +# Python optimizations +ENV PYTHONUNBUFFERED=1 +ENV UV_COMPILE_BYTECODE=1 + +WORKDIR /app + +FROM base AS builder +COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv /bin/ + +WORKDIR /app + +COPY ./projects/api_public ./projects/api_public +COPY ./bases ./bases +COPY ./components ./components + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev --project ./projects/api_public + +FROM base AS dev +COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv uvx/ /bin/ + +WORKDIR /app + +COPY --from=builder /app/projects/api_public/.venv /app/.venv + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +COPY ./projects/api_public ./projects/api_public +COPY ./bases ./bases +COPY ./components ./components + +# this installs dev dependencies +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --project ./projects/api_public \ + && cp -r projects/api_public/.venv/ .venv/ + +CMD ["uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] + +FROM base AS prod + +WORKDIR /app + +# Create a secure user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + +COPY --from=builder --chown=appuser /app/projects/api_public/.venv /app/.venv + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +USER appuser + +CMD ["python3", "-m", "uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] \ No newline at end of file diff --git a/projects/hiscore_scraper/Dockerfile b/projects/hiscore_scraper/Dockerfile index 97b14ba..bc1683f 100644 --- a/projects/hiscore_scraper/Dockerfile +++ b/projects/hiscore_scraper/Dockerfile @@ -1,30 +1,81 @@ -FROM python:3.12-slim-bookworm AS builder +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS base -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ +ENV PYTHONUNBUFFERED=1 \ + UV_COMPILE_BYTECODE=1 -# Set the working directory for the build stage WORKDIR /app -# Copy only necessary files to run the projects + +# ------------------------------------------------------------ +# Builder: runtime-only venv (path is FINAL) +# ------------------------------------------------------------ +FROM base AS builder + +# uv +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv + +# Polylith workspace +COPY ./bases ./bases +COPY ./components ./components +COPY ./projects ./projects +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /app/projects/hiscore_scraper + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev + + +# ------------------------------------------------------------ +# Dev: full workspace + dev deps (own venv) +# ------------------------------------------------------------ +FROM base AS dev + +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ + +ENV PYTHONPATH="/app" + COPY ./bases ./bases COPY ./components ./components COPY ./projects ./projects +COPY workspace.toml workspace.toml WORKDIR /app/projects/hiscore_scraper -# RUN uv build -RUN uv sync --frozen --no-editable +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --dev + +ENV PATH="/app/projects/hiscore_scraper/.venv/bin:$PATH" + +CMD ["hiscore_scraper"] -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production -RUN adduser -u 5678 --disabled-password --gecos "" appuser +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS prod +# Non-root user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser \ + --uid 5678 --disabled-password \ + --no-create-home appuser + +# SAME PATH as builder WORKDIR /app/projects/hiscore_scraper -COPY --from=builder --chown=appuser /app/projects/hiscore_scraper/.venv /app/projects/hiscore_scraper/.venv +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /app/projects/hiscore_scraper/.venv \ + /app/projects/hiscore_scraper/.venv + +ENV PATH="/app/projects/hiscore_scraper/.venv/bin:$PATH" USER appuser -CMD [".venv/bin/hiscore_scraper"] +CMD ["hiscore_scraper"] diff --git a/projects/hiscore_scraper/Dockerfile.bak b/projects/hiscore_scraper/Dockerfile.bak new file mode 100644 index 0000000..bc1683f --- /dev/null +++ b/projects/hiscore_scraper/Dockerfile.bak @@ -0,0 +1,81 @@ +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS base + +ENV PYTHONUNBUFFERED=1 \ + UV_COMPILE_BYTECODE=1 + +WORKDIR /app + + +# ------------------------------------------------------------ +# Builder: runtime-only venv (path is FINAL) +# ------------------------------------------------------------ +FROM base AS builder + +# uv +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv + +# Polylith workspace +COPY ./bases ./bases +COPY ./components ./components +COPY ./projects ./projects +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /app/projects/hiscore_scraper + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev + + +# ------------------------------------------------------------ +# Dev: full workspace + dev deps (own venv) +# ------------------------------------------------------------ +FROM base AS dev + +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ + +ENV PYTHONPATH="/app" + +COPY ./bases ./bases +COPY ./components ./components +COPY ./projects ./projects +COPY workspace.toml workspace.toml + +WORKDIR /app/projects/hiscore_scraper + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --dev + +ENV PATH="/app/projects/hiscore_scraper/.venv/bin:$PATH" + +CMD ["hiscore_scraper"] + + +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS prod + +# Non-root user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser \ + --uid 5678 --disabled-password \ + --no-create-home appuser + +# SAME PATH as builder +WORKDIR /app/projects/hiscore_scraper + +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /app/projects/hiscore_scraper/.venv \ + /app/projects/hiscore_scraper/.venv + +ENV PATH="/app/projects/hiscore_scraper/.venv/bin:$PATH" + +USER appuser + +CMD ["hiscore_scraper"] diff --git a/projects/job_hs_migration_v3/Dockerfile b/projects/job_hs_migration_v3/Dockerfile index a2d128b..24cf61d 100644 --- a/projects/job_hs_migration_v3/Dockerfile +++ b/projects/job_hs_migration_v3/Dockerfile @@ -1,29 +1,54 @@ -FROM python:3.12-slim-bookworm AS builder +FROM python:3.12-slim-bookworm AS base -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ +# Python optimizations +ENV PYTHONUNBUFFERED=1 +ENV UV_COMPILE_BYTECODE=1 -# Set the working directory for the build stage WORKDIR /app -# Copy only necessary files to run the projects +FROM base AS builder +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ + +WORKDIR /app + +COPY ./projects/job_hs_migration_v3 ./projects/job_hs_migration_v3 +COPY ./bases ./bases +COPY ./components ./components + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev --project ./projects/job_hs_migration_v3 + +FROM base AS dev +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ +COPY --from=builder /app/projects/job_hs_migration_v3/.venv /app/.venv + +WORKDIR /app + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +COPY ./projects/job_hs_migration_v3 ./projects/job_hs_migration_v3 COPY ./bases ./bases COPY ./components ./components -COPY ./projects ./projects -WORKDIR /app/projects/job_hs_migration_v3 +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --dev --project ./projects/job_hs_migration_v3 \ + && cp -r projects/job_hs_migration_v3/.venv/ .venv/ -# RUN uv build -RUN uv sync --frozen --no-editable +CMD [".venv/bin/job_hs_migration_v3"] + +FROM base AS prod -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production +WORKDIR /app -RUN adduser -u 5678 --disabled-password --gecos "" appuser +# Create a secure user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser -WORKDIR /app/projects/job_hs_migration_v3 +COPY --from=builder --chown=appuser /app/projects/job_hs_migration_v3/.venv /app/.venv -COPY --from=builder --chown=appuser /app/projects/job_hs_migration_v3/.venv /app/projects/job_hs_migration_v3/.venv +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" USER appuser diff --git a/projects/job_hs_migration_v3/Dockerfile.bak b/projects/job_hs_migration_v3/Dockerfile.bak new file mode 100644 index 0000000..a2d128b --- /dev/null +++ b/projects/job_hs_migration_v3/Dockerfile.bak @@ -0,0 +1,30 @@ +FROM python:3.12-slim-bookworm AS builder + +# Copy uv from external repository +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ + +# Set the working directory for the build stage +WORKDIR /app + +# Copy only necessary files to run the projects +COPY ./bases ./bases +COPY ./components ./components +COPY ./projects ./projects + +WORKDIR /app/projects/job_hs_migration_v3 + +# RUN uv build +RUN uv sync --frozen --no-editable + +# Production stage: Prepare the final production environment +FROM python:3.12-slim-bookworm AS production + +RUN adduser -u 5678 --disabled-password --gecos "" appuser + +WORKDIR /app/projects/job_hs_migration_v3 + +COPY --from=builder --chown=appuser /app/projects/job_hs_migration_v3/.venv /app/projects/job_hs_migration_v3/.venv + +USER appuser + +CMD [".venv/bin/job_hs_migration_v3"] diff --git a/projects/job_prune_hs_data/Dockerfile b/projects/job_prune_hs_data/Dockerfile index 6be8702..aef676c 100644 --- a/projects/job_prune_hs_data/Dockerfile +++ b/projects/job_prune_hs_data/Dockerfile @@ -1,29 +1,54 @@ -FROM python:3.12-slim-bookworm AS builder +FROM python:3.12-slim-bookworm AS base -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ +# Python optimizations +ENV PYTHONUNBUFFERED=1 +ENV UV_COMPILE_BYTECODE=1 -# Set the working directory for the build stage WORKDIR /app -# Copy only necessary files to run the projects +FROM base AS builder +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ + +WORKDIR /app + +COPY ./projects/job_prune_hs_data ./projects/job_prune_hs_data +COPY ./bases ./bases +COPY ./components ./components + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev --project ./projects/job_prune_hs_data + +FROM base AS dev +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ +COPY --from=builder /app/projects/job_prune_hs_data/.venv /app/.venv + +WORKDIR /app + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +COPY ./projects/job_prune_hs_data ./projects/job_prune_hs_data COPY ./bases ./bases COPY ./components ./components -COPY ./projects ./projects -WORKDIR /app/projects/job_prune_hs_data +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --dev --project ./projects/job_prune_hs_data \ + && cp -r projects/job_prune_hs_data/.venv/ .venv/ -# RUN uv build -RUN uv sync --frozen --no-editable +CMD [".venv/bin/job_prune_hs_data"] + +FROM base AS prod -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production +WORKDIR /app -RUN adduser -u 5678 --disabled-password --gecos "" appuser +# Create a secure user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser -WORKDIR /app/projects/job_prune_hs_data +COPY --from=builder --chown=appuser /app/projects/job_prune_hs_data/.venv /app/.venv -COPY --from=builder --chown=appuser /app/projects/job_prune_hs_data/.venv /app/projects/job_prune_hs_data/.venv +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" USER appuser diff --git a/projects/job_prune_hs_data/Dockerfile.bak b/projects/job_prune_hs_data/Dockerfile.bak new file mode 100644 index 0000000..6be8702 --- /dev/null +++ b/projects/job_prune_hs_data/Dockerfile.bak @@ -0,0 +1,30 @@ +FROM python:3.12-slim-bookworm AS builder + +# Copy uv from external repository +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ + +# Set the working directory for the build stage +WORKDIR /app + +# Copy only necessary files to run the projects +COPY ./bases ./bases +COPY ./components ./components +COPY ./projects ./projects + +WORKDIR /app/projects/job_prune_hs_data + +# RUN uv build +RUN uv sync --frozen --no-editable + +# Production stage: Prepare the final production environment +FROM python:3.12-slim-bookworm AS production + +RUN adduser -u 5678 --disabled-password --gecos "" appuser + +WORKDIR /app/projects/job_prune_hs_data + +COPY --from=builder --chown=appuser /app/projects/job_prune_hs_data/.venv /app/projects/job_prune_hs_data/.venv + +USER appuser + +CMD [".venv/bin/job_prune_hs_data"] diff --git a/projects/runemetrics_scraper/Dockerfile b/projects/runemetrics_scraper/Dockerfile index 2b14bd8..68792fa 100644 --- a/projects/runemetrics_scraper/Dockerfile +++ b/projects/runemetrics_scraper/Dockerfile @@ -1,29 +1,54 @@ -FROM python:3.12-slim-bookworm AS builder +FROM python:3.12-slim-bookworm AS base -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ +# Python optimizations +ENV PYTHONUNBUFFERED=1 +ENV UV_COMPILE_BYTECODE=1 -# Set the working directory for the build stage WORKDIR /app -# Copy only necessary files to run the projects +FROM base AS builder +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ + +WORKDIR /app + +COPY ./projects/runemetrics_scraper ./projects/runemetrics_scraper +COPY ./bases ./bases +COPY ./components ./components + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev --project ./projects/runemetrics_scraper + +FROM base AS dev +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ +COPY --from=builder /app/projects/runemetrics_scraper/.venv /app/.venv + +WORKDIR /app + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +COPY ./projects/runemetrics_scraper ./projects/runemetrics_scraper COPY ./bases ./bases COPY ./components ./components -COPY ./projects ./projects -WORKDIR /app/projects/runemetrics_scraper +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --dev --project ./projects/runemetrics_scraper \ + && cp -r projects/runemetrics_scraper/.venv/ .venv/ -# RUN uv build -RUN uv sync --frozen --no-editable +CMD [".venv/bin/runemetrics_scraper"] + +FROM base AS prod -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production +WORKDIR /app -RUN adduser -u 5678 --disabled-password --gecos "" appuser +# Create a secure user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser -WORKDIR /app/projects/runemetrics_scraper +COPY --from=builder --chown=appuser /app/projects/runemetrics_scraper/.venv /app/.venv -COPY --from=builder --chown=appuser /app/projects/runemetrics_scraper/.venv /app/projects/runemetrics_scraper/.venv +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" USER appuser diff --git a/projects/runemetrics_scraper/Dockerfile.bak b/projects/runemetrics_scraper/Dockerfile.bak new file mode 100644 index 0000000..2b14bd8 --- /dev/null +++ b/projects/runemetrics_scraper/Dockerfile.bak @@ -0,0 +1,30 @@ +FROM python:3.12-slim-bookworm AS builder + +# Copy uv from external repository +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ + +# Set the working directory for the build stage +WORKDIR /app + +# Copy only necessary files to run the projects +COPY ./bases ./bases +COPY ./components ./components +COPY ./projects ./projects + +WORKDIR /app/projects/runemetrics_scraper + +# RUN uv build +RUN uv sync --frozen --no-editable + +# Production stage: Prepare the final production environment +FROM python:3.12-slim-bookworm AS production + +RUN adduser -u 5678 --disabled-password --gecos "" appuser + +WORKDIR /app/projects/runemetrics_scraper + +COPY --from=builder --chown=appuser /app/projects/runemetrics_scraper/.venv /app/projects/runemetrics_scraper/.venv + +USER appuser + +CMD [".venv/bin/runemetrics_scraper"] diff --git a/projects/scrape_task_producer/Dockerfile b/projects/scrape_task_producer/Dockerfile index cf5bbc0..4ca2b77 100644 --- a/projects/scrape_task_producer/Dockerfile +++ b/projects/scrape_task_producer/Dockerfile @@ -1,29 +1,54 @@ -FROM python:3.12-slim-bookworm AS builder +FROM python:3.12-slim-bookworm AS base -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ +# Python optimizations +ENV PYTHONUNBUFFERED=1 +ENV UV_COMPILE_BYTECODE=1 -# Set the working directory for the build stage WORKDIR /app -# Copy only necessary files to run the projects +FROM base AS builder +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ + +WORKDIR /app + +COPY ./projects/scrape_task_producer ./projects/scrape_task_producer +COPY ./bases ./bases +COPY ./components ./components + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev --project ./projects/scrape_task_producer + +FROM base AS dev +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ +COPY --from=builder /app/projects/scrape_task_producer/.venv /app/.venv + +WORKDIR /app + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +COPY ./projects/scrape_task_producer ./projects/scrape_task_producer COPY ./bases ./bases COPY ./components ./components -COPY ./projects ./projects -WORKDIR /app/projects/scrape_task_producer +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --dev --project ./projects/scrape_task_producer \ + && cp -r projects/scrape_task_producer/.venv/ .venv/ -# RUN uv build -RUN uv sync --frozen --no-editable +CMD [".venv/bin/scrape_task_producer"] + +FROM base AS prod -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production +WORKDIR /app -RUN adduser -u 5678 --disabled-password --gecos "" appuser +# Create a secure user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser -WORKDIR /app/projects/scrape_task_producer +COPY --from=builder --chown=appuser /app/projects/scrape_task_producer/.venv /app/.venv -COPY --from=builder --chown=appuser /app/projects/scrape_task_producer/.venv /app/projects/scrape_task_producer/.venv +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" USER appuser diff --git a/projects/scrape_task_producer/Dockerfile.bak b/projects/scrape_task_producer/Dockerfile.bak new file mode 100644 index 0000000..cf5bbc0 --- /dev/null +++ b/projects/scrape_task_producer/Dockerfile.bak @@ -0,0 +1,30 @@ +FROM python:3.12-slim-bookworm AS builder + +# Copy uv from external repository +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ + +# Set the working directory for the build stage +WORKDIR /app + +# Copy only necessary files to run the projects +COPY ./bases ./bases +COPY ./components ./components +COPY ./projects ./projects + +WORKDIR /app/projects/scrape_task_producer + +# RUN uv build +RUN uv sync --frozen --no-editable + +# Production stage: Prepare the final production environment +FROM python:3.12-slim-bookworm AS production + +RUN adduser -u 5678 --disabled-password --gecos "" appuser + +WORKDIR /app/projects/scrape_task_producer + +COPY --from=builder --chown=appuser /app/projects/scrape_task_producer/.venv /app/projects/scrape_task_producer/.venv + +USER appuser + +CMD [".venv/bin/scrape_task_producer"] diff --git a/projects/website/Dockerfile b/projects/website/Dockerfile index 211b76e..73d01ce 100644 --- a/projects/website/Dockerfile +++ b/projects/website/Dockerfile @@ -1,30 +1,55 @@ -FROM python:3.12-slim-bookworm AS builder +FROM python:3.12-slim-bookworm AS base -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv /uvx /bin/ +# Python optimizations +ENV PYTHONUNBUFFERED=1 +ENV UV_COMPILE_BYTECODE=1 -# set the working directory WORKDIR /app -# Copy only necessary files to run the projects +FROM base AS builder +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ + +WORKDIR /app + +COPY ./projects/website ./projects/website +COPY ./bases ./bases +COPY ./components ./components + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev --project ./projects/website + +FROM base AS dev +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ +COPY --from=builder /app/projects/website/.venv /app/.venv + +WORKDIR /app + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +COPY ./projects/website ./projects/website COPY ./bases ./bases COPY ./components ./components -COPY ./projects ./projects -WORKDIR /app/projects/website +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --dev --project ./projects/website \ + && cp -r projects/website/.venv/ .venv/ -# install dependencies via RUN uv build -RUN uv sync --frozen --no-editable +CMD ["uvicorn", "bot_detector.website.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] + +FROM base AS prod + +WORKDIR /app -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production +# Create a secure user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser -# Creates a non-root user with an explicit UID and adds permission to access the /project folder -RUN adduser -u 5678 --disabled-password --gecos "" appuser +COPY --from=builder --chown=appuser /app/projects/website/.venv /app/.venv -WORKDIR /app/projects/website -COPY --from=builder --chown=appuser /app/projects/website/.venv /app/projects/website/.venv +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" USER appuser -CMD [".venv/bin/uvicorn", "bot_detector.website.core.server:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] \ No newline at end of file +CMD [".venv/bin/uvicorn", "bot_detector.website.core.server:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] diff --git a/projects/website/Dockerfile.bak b/projects/website/Dockerfile.bak new file mode 100644 index 0000000..211b76e --- /dev/null +++ b/projects/website/Dockerfile.bak @@ -0,0 +1,30 @@ +FROM python:3.12-slim-bookworm AS builder + +# Copy uv from external repository +COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv /uvx /bin/ + +# set the working directory +WORKDIR /app + +# Copy only necessary files to run the projects +COPY ./bases ./bases +COPY ./components ./components +COPY ./projects ./projects + +WORKDIR /app/projects/website + +# install dependencies via RUN uv build +RUN uv sync --frozen --no-editable + +# Production stage: Prepare the final production environment +FROM python:3.12-slim-bookworm AS production + +# Creates a non-root user with an explicit UID and adds permission to access the /project folder +RUN adduser -u 5678 --disabled-password --gecos "" appuser + +WORKDIR /app/projects/website +COPY --from=builder --chown=appuser /app/projects/website/.venv /app/projects/website/.venv + +USER appuser + +CMD [".venv/bin/uvicorn", "bot_detector.website.core.server:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] \ No newline at end of file diff --git a/projects/worker_hiscore/Dockerfile b/projects/worker_hiscore/Dockerfile index 4ccbddd..2efe4c8 100644 --- a/projects/worker_hiscore/Dockerfile +++ b/projects/worker_hiscore/Dockerfile @@ -1,29 +1,54 @@ -FROM python:3.12-slim-bookworm AS builder +FROM python:3.12-slim-bookworm AS base -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ +# Python optimizations +ENV PYTHONUNBUFFERED=1 +ENV UV_COMPILE_BYTECODE=1 -# Set the working directory for the build stage WORKDIR /app -# Copy only necessary files to run the projects +FROM base AS builder +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ + +WORKDIR /app + +COPY ./projects/worker_hiscore ./projects/worker_hiscore +COPY ./bases ./bases +COPY ./components ./components + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev --project ./projects/worker_hiscore + +FROM base AS dev +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ +COPY --from=builder /app/projects/worker_hiscore/.venv /app/.venv + +WORKDIR /app + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +COPY ./projects/worker_hiscore ./projects/worker_hiscore COPY ./bases ./bases COPY ./components ./components -COPY ./projects ./projects -WORKDIR /app/projects/worker_hiscore +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --dev --project ./projects/worker_hiscore \ + && cp -r projects/worker_hiscore/.venv/ .venv/ -# RUN uv build -RUN uv sync --frozen --no-editable +CMD [".venv/bin/worker_hiscore"] + +FROM base AS prod -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production +WORKDIR /app -RUN adduser -u 5678 --disabled-password --gecos "" appuser +# Create a secure user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser -WORKDIR /app/projects/worker_hiscore +COPY --from=builder --chown=appuser /app/projects/worker_hiscore/.venv /app/.venv -COPY --from=builder --chown=appuser /app/projects/worker_hiscore/.venv /app/projects/worker_hiscore/.venv +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" USER appuser diff --git a/projects/worker_hiscore/Dockerfile.bak b/projects/worker_hiscore/Dockerfile.bak new file mode 100644 index 0000000..4ccbddd --- /dev/null +++ b/projects/worker_hiscore/Dockerfile.bak @@ -0,0 +1,30 @@ +FROM python:3.12-slim-bookworm AS builder + +# Copy uv from external repository +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ + +# Set the working directory for the build stage +WORKDIR /app + +# Copy only necessary files to run the projects +COPY ./bases ./bases +COPY ./components ./components +COPY ./projects ./projects + +WORKDIR /app/projects/worker_hiscore + +# RUN uv build +RUN uv sync --frozen --no-editable + +# Production stage: Prepare the final production environment +FROM python:3.12-slim-bookworm AS production + +RUN adduser -u 5678 --disabled-password --gecos "" appuser + +WORKDIR /app/projects/worker_hiscore + +COPY --from=builder --chown=appuser /app/projects/worker_hiscore/.venv /app/projects/worker_hiscore/.venv + +USER appuser + +CMD [".venv/bin/worker_hiscore"] diff --git a/projects/worker_ml/Dockerfile b/projects/worker_ml/Dockerfile index 648d1ed..0013e4a 100644 --- a/projects/worker_ml/Dockerfile +++ b/projects/worker_ml/Dockerfile @@ -1,29 +1,54 @@ -FROM python:3.12-slim-bookworm AS builder +FROM python:3.12-slim-bookworm AS base -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ +# Python optimizations +ENV PYTHONUNBUFFERED=1 +ENV UV_COMPILE_BYTECODE=1 -# Set the working directory for the build stage WORKDIR /app -# Copy only necessary files to run the projects +FROM base AS builder +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ + +WORKDIR /app + +COPY ./projects/worker_ml ./projects/worker_ml +COPY ./bases ./bases +COPY ./components ./components + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev --project ./projects/worker_ml + +FROM base AS dev +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ +COPY --from=builder /app/projects/worker_ml/.venv /app/.venv + +WORKDIR /app + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +COPY ./projects/worker_ml ./projects/worker_ml COPY ./bases ./bases COPY ./components ./components -COPY ./projects ./projects -WORKDIR /app/projects/worker_ml +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --dev --project ./projects/worker_ml \ + && cp -r projects/worker_ml/.venv/ .venv/ -# RUN uv build -RUN uv sync --frozen --no-editable +CMD [".venv/bin/worker_ml"] + +FROM base AS prod -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production +WORKDIR /app -RUN adduser -u 5678 --disabled-password --gecos "" appuser +# Create a secure user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser -WORKDIR /app/projects/worker_ml +COPY --from=builder --chown=appuser /app/projects/worker_ml/.venv /app/.venv -COPY --from=builder --chown=appuser /app/projects/worker_ml/.venv /app/projects/worker_ml/.venv +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" USER appuser diff --git a/projects/worker_ml/Dockerfile.bak b/projects/worker_ml/Dockerfile.bak new file mode 100644 index 0000000..648d1ed --- /dev/null +++ b/projects/worker_ml/Dockerfile.bak @@ -0,0 +1,30 @@ +FROM python:3.12-slim-bookworm AS builder + +# Copy uv from external repository +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ + +# Set the working directory for the build stage +WORKDIR /app + +# Copy only necessary files to run the projects +COPY ./bases ./bases +COPY ./components ./components +COPY ./projects ./projects + +WORKDIR /app/projects/worker_ml + +# RUN uv build +RUN uv sync --frozen --no-editable + +# Production stage: Prepare the final production environment +FROM python:3.12-slim-bookworm AS production + +RUN adduser -u 5678 --disabled-password --gecos "" appuser + +WORKDIR /app/projects/worker_ml + +COPY --from=builder --chown=appuser /app/projects/worker_ml/.venv /app/projects/worker_ml/.venv + +USER appuser + +CMD [".venv/bin/worker_ml"] diff --git a/projects/worker_report/Dockerfile b/projects/worker_report/Dockerfile index 372cd31..9c070e7 100644 --- a/projects/worker_report/Dockerfile +++ b/projects/worker_report/Dockerfile @@ -1,29 +1,54 @@ -FROM python:3.12-slim-bookworm AS builder +FROM python:3.12-slim-bookworm AS base -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ +# Python optimizations +ENV PYTHONUNBUFFERED=1 +ENV UV_COMPILE_BYTECODE=1 -# Set the working directory for the build stage WORKDIR /app -# Copy only necessary files to run the projects +FROM base AS builder +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ + +WORKDIR /app + +COPY ./projects/worker_report ./projects/worker_report +COPY ./bases ./bases +COPY ./components ./components + +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev --project ./projects/worker_report + +FROM base AS dev +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ +COPY --from=builder /app/projects/worker_report/.venv /app/.venv + +WORKDIR /app + +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" + +COPY ./projects/worker_report ./projects/worker_report COPY ./bases ./bases COPY ./components ./components -COPY ./projects ./projects -WORKDIR /app/projects/worker_report +RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ + uv sync --dev --project ./projects/worker_report \ + && cp -r projects/worker_report/.venv/ .venv/ -# RUN uv build -RUN uv sync --frozen --no-editable +CMD [".venv/bin/worker_report"] + +FROM base AS prod -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production +WORKDIR /app -RUN adduser -u 5678 --disabled-password --gecos "" appuser +# Create a secure user +RUN addgroup --system appuser && \ + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser -WORKDIR /app/projects/worker_report +COPY --from=builder --chown=appuser /app/projects/worker_report/.venv /app/.venv -COPY --from=builder --chown=appuser /app/projects/worker_report/.venv /app/projects/worker_report/.venv +ENV PATH="/app/.venv/bin:$PATH" +ENV PYTHONPATH="/app" USER appuser diff --git a/projects/worker_report/Dockerfile.bak b/projects/worker_report/Dockerfile.bak new file mode 100644 index 0000000..372cd31 --- /dev/null +++ b/projects/worker_report/Dockerfile.bak @@ -0,0 +1,30 @@ +FROM python:3.12-slim-bookworm AS builder + +# Copy uv from external repository +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ + +# Set the working directory for the build stage +WORKDIR /app + +# Copy only necessary files to run the projects +COPY ./bases ./bases +COPY ./components ./components +COPY ./projects ./projects + +WORKDIR /app/projects/worker_report + +# RUN uv build +RUN uv sync --frozen --no-editable + +# Production stage: Prepare the final production environment +FROM python:3.12-slim-bookworm AS production + +RUN adduser -u 5678 --disabled-password --gecos "" appuser + +WORKDIR /app/projects/worker_report + +COPY --from=builder --chown=appuser /app/projects/worker_report/.venv /app/projects/worker_report/.venv + +USER appuser + +CMD [".venv/bin/worker_report"] From dcfa3619798850f95aa20f0e36d6b039584bc573 Mon Sep 17 00:00:00 2001 From: extreme4all <> Date: Sat, 24 Jan 2026 19:14:16 +0100 Subject: [PATCH 2/5] checkpoitn --- docker-compose-dev.yml | 104 ++++++++++++-------------------- docker-compose.yml | 106 ++++++++++++--------------------- projects/api_ml/Dockerfile | 21 ++++++- projects/api_public/Dockerfile | 23 +++++-- 4 files changed, 112 insertions(+), 142 deletions(-) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 7f1c508..74e73b3 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -1,4 +1,4 @@ -# this compose file is used for local development and testing +# this docker-compose file is used for local development and testing services: # KAFKA kafka: @@ -33,12 +33,12 @@ services: retries: 5 networks: - botdetector-network + kafka_setup: container_name: kafka_setup - image: bd/kafka_setup # tags the image if build + image: bd/kafka_setup build: context: ./_kafka - # command: ["sleep", "infinity"] environment: - KAFKA_BROKER=kafka:9092 networks: @@ -46,6 +46,7 @@ services: depends_on: kafka: condition: service_healthy + kafdrop: container_name: kafdrop image: obsidiandynamics/kafdrop:latest @@ -54,22 +55,22 @@ services: - JVM_OPTS=-Xms32M -Xmx64M - SERVER_SERVLET_CONTEXTPATH=/ ports: - - 9042:9000 # too many things use 9000 like portainer.. lets use 9042 instead? + - 9042:9000 restart: on-failure networks: - botdetector-network depends_on: kafka: condition: service_healthy + # MYSQL mysql: container_name: mysql - image: bd/mysql # tags the image if build + image: bd/mysql build: context: ./_mysql environment: - MYSQL_ROOT_PASSWORD=root_bot_buster - # - MYSQL_DATABASE=playerdata ports: - 3307:3306 networks: @@ -80,12 +81,12 @@ services: retries: 3 start_period: 30s timeout: 5s + mysql_setup: container_name: mysql_setup - image: bd/mysql_setup # tags the image if build + image: bd/mysql_setup build: context: ./_mysql_data - # command: ["sleep", "infinity"] environment: - DATABASE_URL=mysql+asyncmy://root:root_bot_buster@mysql:3306/playerdata - DEBUG=False @@ -94,6 +95,7 @@ services: depends_on: mysql: condition: service_healthy + # MINIO minio: image: minio/minio @@ -109,13 +111,14 @@ services: volumes: - ./_minio_data:/data healthcheck: - test: timeout 5s bash -c ':> /dev/tcp/127.0.0.1/9000' || exit 1 + test: timeout 5s bash -c ':> /dev/tcp/127.0.0.1:9000' || exit 1 interval: 1s timeout: 10s retries: 5 command: server /data --console-address ":9001" networks: - botdetector-network + # Create a bucket named "bucket" if it doesn't exist minio-create-bucket: image: minio/mc @@ -132,6 +135,7 @@ services: echo 'bucket already exists' fi " + # COMPONENTS hiscore_scraper: container_name: hiscore_scraper @@ -140,49 +144,40 @@ services: context: ./ dockerfile: ./projects/hiscore_scraper/Dockerfile target: dev - # command: ["sleep", "infinity"] networks: - botdetector-network env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka_setup: condition: service_completed_successfully + runemetrics_scraper: container_name: runemetrics_scraper - image: bd/runemetrics_scraper + image: bd/runemetrics_scraper:dev build: context: ./ dockerfile: ./projects/runemetrics_scraper/Dockerfile target: dev - # command: ["sleep", "infinity"] - # command: ["uv", "run", "bot_detector/runemetrics_scraper/src/core.py"] networks: - botdetector-network env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka_setup: condition: service_completed_successfully + worker_hiscore: container_name: worker_hiscore - image: bd/worker_hiscore + image: bd/worker_hiscore:dev build: context: ./ dockerfile: ./projects/worker_hiscore/Dockerfile target: dev - # command: ["sleep", "infinity"] - # command: ["uv", "run", "bot_detector/worker_hiscore/src/core.py"] networks: - botdetector-network env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka: condition: service_healthy @@ -192,33 +187,31 @@ services: condition: service_healthy mysql_setup: condition: service_completed_successfully + worker_report: container_name: worker_report - image: bd/worker_report + image: bd/worker_report:dev build: context: ./ dockerfile: ./projects/worker_report/Dockerfile target: dev - # command: ["sleep", "infinity"] networks: - botdetector-network env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka_setup: condition: service_completed_successfully mysql_setup: condition: service_completed_successfully + worker_ml: container_name: worker_ml - image: bd/worker_ml + image: bd/worker_ml:dev build: context: ./ dockerfile: ./projects/worker_ml/Dockerfile target: dev - # command: ["sleep", "infinity"] environment: - DATABASE_URL=mysql+asyncmy://ml-worker:ml_worker_pw@mysql:3306/playerdata - KAFKA_BOOTSTRAP_SERVERS=kafka:9092 @@ -226,10 +219,11 @@ services: - MAX_MESSAGES=10 - MAX_INTERVAL_MS=5000 - MODEL_NAME=multi_model_v1 + volumes: + - ./bases:/app/bases + - ./components:/app/components networks: - botdetector-network - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka_setup: condition: service_completed_successfully @@ -237,34 +231,31 @@ services: condition: service_completed_successfully api_ml: condition: service_healthy - + scrape_task_producer: container_name: scrape_task_producer - image: bd/scrape_task_producer + image: bd/scrape_task_producer:dev build: context: ./ dockerfile: ./projects/scrape_task_producer/Dockerfile target: dev - # command: ["sleep", "infinity"] networks: - botdetector-network env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka_setup: condition: service_completed_successfully mysql_setup: condition: service_completed_successfully + job_prune_hs_data: container_name: job_prune_hs_data - image: bd/job_prune_hs_data + image: bd/job_prune_hs_data:dev build: context: ./ dockerfile: ./projects/job_prune_hs_data/Dockerfile target: dev - # command: ["sleep", "infinity"] networks: - botdetector-network environment: @@ -272,11 +263,10 @@ services: - DATABASE_URL=mysql+asyncmy://job-prune-hs:job_prune_hs_pw@mysql:3306/playerdata env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: mysql_setup: condition: service_completed_successfully + api_public: container_name: api_public image: bd/api_public:dev @@ -284,7 +274,6 @@ services: context: . dockerfile: ./projects/api_public/Dockerfile target: dev - # command: ["sleep", "infinity"] env_file: - .env environment: @@ -294,9 +283,8 @@ services: - POOL_RECYCLE=60 - POOL_TIMEOUT=30 volumes: - - ./bases:/bases - - ./components:/components - # - uv_cache:/root/.cache/uv + - ./bases:/app/bases + - ./components:/app/components ports: - 5000 networks: @@ -312,18 +300,10 @@ services: timeout: 5s retries: 3 start_period: 30s - wait_for_api_public: - image: alpine:latest - container_name: wait_for_api_public - command: ["sh", "-c", "echo 'api_public healthy'"] - depends_on: - api_public: - condition: service_healthy - networks: - - botdetector-network + website: container_name: website - image: bd/website + image: bd/website:dev build: context: . dockerfile: ./projects/website/Dockerfile @@ -337,7 +317,8 @@ services: PATREON_CLIENT_ID: "" PATREON_CLIENT_SECRET: "" volumes: - - uv_cache:/root/.cache/uv + - ./bases:/app/bases + - ./components:/app/components ports: - 5000 networks: @@ -350,12 +331,11 @@ services: start_period: 30s api_ml: container_name: api_ml - image: bd/api_ml + image: bd/api_ml:dev build: context: . dockerfile: ./projects/api_ml/Dockerfile target: dev - # command: ["sleep", "infinity"] env_file: - .env environment: @@ -363,12 +343,6 @@ services: - AWS_ACCESS_KEY_ID=minio_user - AWS_SECRET_ACCESS_KEY=minio_password - UV_HTTP_TIMEOUT=120 - volumes: - - ./bases:/app/bases - - ./components:/app/components - - uv_cache:/root/.cache/uv - ports: - - 5001:5000 networks: - botdetector-network depends_on: @@ -383,8 +357,4 @@ services: networks: botdetector-network: - name: bd-network - -volumes: - uv_cache: - external: true \ No newline at end of file + name: bd-network \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 4dca7d7..3b6c5c1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -# this docker-compose file is used to simulate production environment +# this docker-compose file is used for production deployment services: # KAFKA kafka: @@ -33,12 +33,12 @@ services: retries: 5 networks: - botdetector-network + kafka_setup: container_name: kafka_setup - image: bd/kafka_setup # tags the image if build + image: bd/kafka_setup build: context: ./_kafka - # command: ["sleep", "infinity"] environment: - KAFKA_BROKER=kafka:9092 networks: @@ -46,6 +46,7 @@ services: depends_on: kafka: condition: service_healthy + kafdrop: container_name: kafdrop image: obsidiandynamics/kafdrop:latest @@ -54,22 +55,22 @@ services: - JVM_OPTS=-Xms32M -Xmx64M - SERVER_SERVLET_CONTEXTPATH=/ ports: - - 9042:9000 # too many things use 9000 like portainer.. lets use 9042 instead? + - 9042:9000 restart: on-failure networks: - botdetector-network depends_on: kafka: condition: service_healthy + # MYSQL mysql: container_name: mysql - image: bd/mysql # tags the image if build + image: bd/mysql build: context: ./_mysql environment: - MYSQL_ROOT_PASSWORD=root_bot_buster - # - MYSQL_DATABASE=playerdata ports: - 3307:3306 networks: @@ -80,12 +81,12 @@ services: retries: 3 start_period: 30s timeout: 5s + mysql_setup: container_name: mysql_setup - image: bd/mysql_setup # tags the image if build + image: bd/mysql_setup build: context: ./_mysql_data - # command: ["sleep", "infinity"] environment: - DATABASE_URL=mysql+asyncmy://root:root_bot_buster@mysql:3306/playerdata - DEBUG=False @@ -94,9 +95,11 @@ services: depends_on: mysql: condition: service_healthy + # MINIO minio: image: minio/minio + container_name: minio expose: - "9000" - "9001" @@ -115,9 +118,11 @@ services: command: server /data --console-address ":9001" networks: - botdetector-network + # Create a bucket named "bucket" if it doesn't exist minio-create-bucket: image: minio/mc + container_name: minio_create_bucket depends_on: minio: condition: service_healthy @@ -130,6 +135,9 @@ services: echo 'bucket already exists' fi " + networks: + - botdetector-network + # COMPONENTS hiscore_scraper: container_name: hiscore_scraper @@ -138,49 +146,40 @@ services: context: ./ dockerfile: ./projects/hiscore_scraper/Dockerfile target: prod - # command: ["sleep", "infinity"] networks: - botdetector-network env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka_setup: condition: service_completed_successfully + runemetrics_scraper: container_name: runemetrics_scraper - image: bd/runemetrics_scraper + image: bd/runemetrics_scraper:prd build: context: ./ dockerfile: ./projects/runemetrics_scraper/Dockerfile target: prod - # command: ["sleep", "infinity"] - # command: ["uv", "run", "bot_detector/runemetrics_scraper/src/core.py"] networks: - botdetector-network env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka_setup: condition: service_completed_successfully + worker_hiscore: container_name: worker_hiscore - image: bd/worker_hiscore + image: bd/worker_hiscore:prd build: context: ./ dockerfile: ./projects/worker_hiscore/Dockerfile target: prod - # command: ["sleep", "infinity"] - # command: ["uv", "run", "bot_detector/worker_hiscore/src/core.py"] networks: - botdetector-network env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka: condition: service_healthy @@ -190,33 +189,31 @@ services: condition: service_healthy mysql_setup: condition: service_completed_successfully + worker_report: container_name: worker_report - image: bd/worker_report + image: bd/worker_report:prd build: context: ./ dockerfile: ./projects/worker_report/Dockerfile target: prod - # command: ["sleep", "infinity"] networks: - botdetector-network env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka_setup: condition: service_completed_successfully mysql_setup: condition: service_completed_successfully + worker_ml: container_name: worker_ml - image: bd/worker_ml + image: bd/worker_ml:prd build: context: ./ dockerfile: ./projects/worker_ml/Dockerfile target: prod - # command: ["sleep", "infinity"] environment: - DATABASE_URL=mysql+asyncmy://ml-worker:ml_worker_pw@mysql:3306/playerdata - KAFKA_BOOTSTRAP_SERVERS=kafka:9092 @@ -226,8 +223,6 @@ services: - MODEL_NAME=multi_model_v1 networks: - botdetector-network - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka_setup: condition: service_completed_successfully @@ -235,33 +230,31 @@ services: condition: service_completed_successfully api_ml: condition: service_healthy + scrape_task_producer: container_name: scrape_task_producer - image: bd/scrape_task_producer + image: bd/scrape_task_producer:prd build: context: ./ dockerfile: ./projects/scrape_task_producer/Dockerfile target: prod - # command: ["sleep", "infinity"] networks: - botdetector-network env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: kafka_setup: condition: service_completed_successfully mysql_setup: condition: service_completed_successfully + job_prune_hs_data: container_name: job_prune_hs_data - image: bd/job_prune_hs_data + image: bd/job_prune_hs_data:prd build: context: ./ dockerfile: ./projects/job_prune_hs_data/Dockerfile target: prod - # command: ["sleep", "infinity"] networks: - botdetector-network environment: @@ -269,19 +262,17 @@ services: - DATABASE_URL=mysql+asyncmy://job-prune-hs:job_prune_hs_pw@mysql:3306/playerdata env_file: - .env - volumes: - - uv_cache:/root/.cache/uv depends_on: mysql_setup: condition: service_completed_successfully + api_public: container_name: api_public - image: bd/api_public:prod + image: bd/api_public:prd build: context: . dockerfile: ./projects/api_public/Dockerfile target: prod - # command: ["sleep", "infinity"] env_file: - .env environment: @@ -290,10 +281,7 @@ services: - ENV=DEV - POOL_RECYCLE=60 - POOL_TIMEOUT=30 - volumes: - - ./bases:/app/bases - - ./components:/app/components - ports: + ports: - 5000 networks: - botdetector-network @@ -308,18 +296,10 @@ services: timeout: 5s retries: 3 start_period: 30s - wait_for_api_public: - image: alpine:latest - container_name: wait_for_api_public - command: ["sh", "-c", "echo 'api_public healthy'"] - depends_on: - api_public: - condition: service_healthy - networks: - - botdetector-network + website: container_name: website - image: bd/website + image: bd/website:prd build: context: . dockerfile: ./projects/website/Dockerfile @@ -332,10 +312,6 @@ services: RELEASE_VERSION: "0.1" PATREON_CLIENT_ID: "" PATREON_CLIENT_SECRET: "" - volumes: - - uv_cache:/root/.cache/uv - ports: - - 5000 networks: - botdetector-network healthcheck: @@ -344,14 +320,14 @@ services: timeout: 5s retries: 3 start_period: 30s + api_ml: container_name: api_ml - image: bd/api_ml + image: bd/api_ml:prd build: context: . dockerfile: ./projects/api_ml/Dockerfile target: prod - # command: ["sleep", "infinity"] env_file: - .env environment: @@ -359,12 +335,8 @@ services: - AWS_ACCESS_KEY_ID=minio_user - AWS_SECRET_ACCESS_KEY=minio_password - UV_HTTP_TIMEOUT=120 - volumes: - - ./bases:/app/bases - - ./components:/app/components - - uv_cache:/root/.cache/uv ports: - - 5001:5000 + - 5000 networks: - botdetector-network depends_on: @@ -379,8 +351,4 @@ services: networks: botdetector-network: - name: bd-network - -volumes: - uv_cache: - external: true \ No newline at end of file + name: bd-network \ No newline at end of file diff --git a/projects/api_ml/Dockerfile b/projects/api_ml/Dockerfile index e5a783e..86589ba 100644 --- a/projects/api_ml/Dockerfile +++ b/projects/api_ml/Dockerfile @@ -1,3 +1,6 @@ +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base # Python optimizations @@ -6,7 +9,12 @@ ENV UV_COMPILE_BYTECODE=1 WORKDIR /app + +# ------------------------------------------------------------ +# Builder: production dependencies only +# ------------------------------------------------------------ FROM base AS builder + COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ WORKDIR /app @@ -18,7 +26,12 @@ COPY ./components ./components RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ uv sync --frozen --no-dev --project ./projects/api_ml + +# ------------------------------------------------------------ +# Dev: development environment with dev dependencies +# ------------------------------------------------------------ FROM base AS dev + COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ WORKDIR /app @@ -36,13 +49,17 @@ RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ CMD ["uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] + +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ FROM base AS prod WORKDIR /app # Create a secure user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 1000 appuser COPY --from=builder --chown=appuser /app/projects/api_ml/.venv /app/.venv @@ -51,4 +68,4 @@ ENV PYTHONPATH="/app" USER appuser -CMD ["python3", "-m", "uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] \ No newline at end of file +CMD ["python3", "-m", "uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] diff --git a/projects/api_public/Dockerfile b/projects/api_public/Dockerfile index 7e2bac5..4574240 100644 --- a/projects/api_public/Dockerfile +++ b/projects/api_public/Dockerfile @@ -1,3 +1,6 @@ +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base # Python optimizations @@ -6,7 +9,12 @@ ENV UV_COMPILE_BYTECODE=1 WORKDIR /app + +# ------------------------------------------------------------ +# Builder: production dependencies only +# ------------------------------------------------------------ FROM base AS builder + COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ WORKDIR /app @@ -18,13 +26,16 @@ COPY ./components ./components RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ uv sync --frozen --no-dev --project ./projects/api_public + +# ------------------------------------------------------------ +# Dev: development environment with dev dependencies +# ------------------------------------------------------------ FROM base AS dev + COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ WORKDIR /app -COPY --from=builder /app/projects/api_public/.venv /app/.venv - ENV PATH="/app/.venv/bin:$PATH" ENV PYTHONPATH="/app" @@ -38,13 +49,17 @@ RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ CMD ["uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] + +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ FROM base AS prod WORKDIR /app # Create a secure user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 1000 appuser COPY --from=builder --chown=appuser /app/projects/api_public/.venv /app/.venv @@ -53,4 +68,4 @@ ENV PYTHONPATH="/app" USER appuser -CMD ["python3", "-m", "uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] \ No newline at end of file +CMD ["python3", "-m", "uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] From d7781a69e33ee24d1d511a12d582cc14fe8f4942 Mon Sep 17 00:00:00 2001 From: extreme4all <> Date: Sat, 24 Jan 2026 19:31:39 +0100 Subject: [PATCH 3/5] checkpoint --- projects/api_ml/Dockerfile | 20 ++++++++++---------- projects/api_public/Dockerfile | 20 ++++++++++---------- projects/hiscore_scraper/Dockerfile | 18 +++++++++--------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/projects/api_ml/Dockerfile b/projects/api_ml/Dockerfile index 86589ba..a261879 100644 --- a/projects/api_ml/Dockerfile +++ b/projects/api_ml/Dockerfile @@ -7,7 +7,7 @@ FROM python:3.12-slim-bookworm AS base ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 -WORKDIR /app +WORKDIR /project # ------------------------------------------------------------ @@ -17,7 +17,7 @@ FROM base AS builder COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ -WORKDIR /app +WORKDIR /project COPY ./projects/api_ml ./projects/api_ml COPY ./bases ./bases @@ -34,10 +34,10 @@ FROM base AS dev COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ -WORKDIR /app +WORKDIR /project -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/.venv/bin:$PATH" +ENV PYTHONPATH="/project" COPY ./projects/api_ml ./projects/api_ml COPY ./bases ./bases @@ -55,16 +55,16 @@ CMD ["uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--p # ------------------------------------------------------------ FROM base AS prod -WORKDIR /app +WORKDIR /project # Create a secure user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 1000 appuser + adduser --system --ingroup appuser --home /project --no-create-home --disabled-password --uid 1000 appuser -COPY --from=builder --chown=appuser /app/projects/api_ml/.venv /app/.venv +COPY --from=builder --chown=appuser /project/projects/api_ml/.venv /project/.venv -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/.venv/bin:$PATH" +ENV PYTHONPATH="/project" USER appuser diff --git a/projects/api_public/Dockerfile b/projects/api_public/Dockerfile index 4574240..d25ed6a 100644 --- a/projects/api_public/Dockerfile +++ b/projects/api_public/Dockerfile @@ -7,7 +7,7 @@ FROM python:3.12-slim-bookworm AS base ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 -WORKDIR /app +WORKDIR /project # ------------------------------------------------------------ @@ -17,7 +17,7 @@ FROM base AS builder COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ -WORKDIR /app +WORKDIR /project COPY ./projects/api_public ./projects/api_public COPY ./bases ./bases @@ -34,10 +34,10 @@ FROM base AS dev COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ -WORKDIR /app +WORKDIR /project -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/.venv/bin:$PATH" +ENV PYTHONPATH="/project" COPY ./projects/api_public ./projects/api_public COPY ./bases ./bases @@ -55,16 +55,16 @@ CMD ["uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0. # ------------------------------------------------------------ FROM base AS prod -WORKDIR /app +WORKDIR /project # Create a secure user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 1000 appuser + adduser --system --ingroup appuser --home /project --no-create-home --disabled-password --uid 1000 appuser -COPY --from=builder --chown=appuser /app/projects/api_public/.venv /app/.venv +COPY --from=builder --chown=appuser /project/projects/api_public/.venv /project/.venv -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/.venv/bin:$PATH" +ENV PYTHONPATH="/project" USER appuser diff --git a/projects/hiscore_scraper/Dockerfile b/projects/hiscore_scraper/Dockerfile index bc1683f..50309d3 100644 --- a/projects/hiscore_scraper/Dockerfile +++ b/projects/hiscore_scraper/Dockerfile @@ -6,7 +6,7 @@ FROM python:3.12-slim-bookworm AS base ENV PYTHONUNBUFFERED=1 \ UV_COMPILE_BYTECODE=1 -WORKDIR /app +WORKDIR /project # ------------------------------------------------------------ @@ -24,7 +24,7 @@ COPY ./projects ./projects COPY workspace.toml workspace.toml # IMPORTANT: venv path is fixed here -WORKDIR /app/projects/hiscore_scraper +WORKDIR /project/projects/hiscore_scraper RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ uv sync --frozen --no-dev @@ -37,19 +37,19 @@ FROM base AS dev COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ -ENV PYTHONPATH="/app" +ENV PYTHONPATH="/project" COPY ./bases ./bases COPY ./components ./components COPY ./projects ./projects COPY workspace.toml workspace.toml -WORKDIR /app/projects/hiscore_scraper +WORKDIR /project/projects/hiscore_scraper RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ uv sync --dev -ENV PATH="/app/projects/hiscore_scraper/.venv/bin:$PATH" +ENV PATH="/project/projects/hiscore_scraper/.venv/bin:$PATH" CMD ["hiscore_scraper"] @@ -66,15 +66,15 @@ RUN addgroup --system appuser && \ --no-create-home appuser # SAME PATH as builder -WORKDIR /app/projects/hiscore_scraper +WORKDIR /project/projects/hiscore_scraper # Copy sealed venv (no relocation!) COPY --from=builder \ --chown=appuser:appuser \ - /app/projects/hiscore_scraper/.venv \ - /app/projects/hiscore_scraper/.venv + /project/projects/hiscore_scraper/.venv \ + /project/projects/hiscore_scraper/.venv -ENV PATH="/app/projects/hiscore_scraper/.venv/bin:$PATH" +ENV PATH="/project/projects/hiscore_scraper/.venv/bin:$PATH" USER appuser From 48330848f0ea630b6e83997e843830abf237b557 Mon Sep 17 00:00:00 2001 From: extreme4all <> Date: Sat, 24 Jan 2026 21:32:06 +0100 Subject: [PATCH 4/5] everything seems working --- README.md | 7 +- docker-compose-dev.yml | 15 ++-- projects/api_ml/Dockerfile | 53 +++++++------ projects/api_ml/Dockerfile.bak | 56 -------------- projects/api_public/Dockerfile | 53 +++++++------ projects/api_public/Dockerfile.bak | 57 -------------- projects/hiscore_scraper/Dockerfile | 20 ++--- projects/hiscore_scraper/Dockerfile.bak | 81 -------------------- projects/job_hs_migration_v3/Dockerfile | 75 ++++++++++++------ projects/job_hs_migration_v3/Dockerfile.bak | 30 -------- projects/job_prune_hs_data/Dockerfile | 75 ++++++++++++------ projects/job_prune_hs_data/Dockerfile.bak | 30 -------- projects/runemetrics_scraper/Dockerfile | 75 ++++++++++++------ projects/runemetrics_scraper/Dockerfile.bak | 30 -------- projects/scrape_task_producer/Dockerfile | 75 ++++++++++++------ projects/scrape_task_producer/Dockerfile.bak | 30 -------- projects/website/Dockerfile | 73 ++++++++++++------ projects/website/Dockerfile.bak | 30 -------- projects/worker_hiscore/Dockerfile | 75 ++++++++++++------ projects/worker_hiscore/Dockerfile.bak | 30 -------- projects/worker_ml/Dockerfile | 75 ++++++++++++------ projects/worker_ml/Dockerfile.bak | 30 -------- projects/worker_report/Dockerfile | 75 ++++++++++++------ projects/worker_report/Dockerfile.bak | 30 -------- 24 files changed, 491 insertions(+), 689 deletions(-) delete mode 100644 projects/api_ml/Dockerfile.bak delete mode 100644 projects/api_public/Dockerfile.bak delete mode 100644 projects/hiscore_scraper/Dockerfile.bak delete mode 100644 projects/job_hs_migration_v3/Dockerfile.bak delete mode 100644 projects/job_prune_hs_data/Dockerfile.bak delete mode 100644 projects/runemetrics_scraper/Dockerfile.bak delete mode 100644 projects/scrape_task_producer/Dockerfile.bak delete mode 100644 projects/website/Dockerfile.bak delete mode 100644 projects/worker_hiscore/Dockerfile.bak delete mode 100644 projects/worker_ml/Dockerfile.bak delete mode 100644 projects/worker_report/Dockerfile.bak diff --git a/README.md b/README.md index 88da561..c889a26 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,12 @@ flowchart TD ```sh find . -type f -name "pyproject.toml" -not -path "*/.venv/*" -execdir sh -c 'echo "🔄 Updating lock in $(pwd)"; uv lock' \; ``` -# syncing in all directories, so uv cache is setup ```sh find . -type f -name "pyproject.toml" -not -path "*/.venv/*" -execdir sh -c 'echo "🔄 syncing in $(pwd)"; uv sync' \; +``` +```sh +find . -type f -name "pyproject.toml" -not -path "*/.venv/*" -execdir sh -c 'echo "🔄 Removing venv in $(pwd)"; rm -rf .venv/' \; +``` +```sh +find . -type f -name "pyproject.toml" -not -path "*/.venv/*" -execdir sh -c 'echo "🔄 Removing Dockerfile.bak in $(pwd)"; rm Dockerfile.bak' \; ``` \ No newline at end of file diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml index 74e73b3..debafca 100644 --- a/docker-compose-dev.yml +++ b/docker-compose-dev.yml @@ -111,7 +111,7 @@ services: volumes: - ./_minio_data:/data healthcheck: - test: timeout 5s bash -c ':> /dev/tcp/127.0.0.1:9000' || exit 1 + test: timeout 5s bash -c ':> /dev/tcp/127.0.0.1/9000' || exit 1 interval: 1s timeout: 10s retries: 5 @@ -220,8 +220,8 @@ services: - MAX_INTERVAL_MS=5000 - MODEL_NAME=multi_model_v1 volumes: - - ./bases:/app/bases - - ./components:/app/components + - ./bases:/project/bases + - ./components:/project/components networks: - botdetector-network depends_on: @@ -283,8 +283,8 @@ services: - POOL_RECYCLE=60 - POOL_TIMEOUT=30 volumes: - - ./bases:/app/bases - - ./components:/app/components + - ./bases:/project/bases + - ./components:/project/components ports: - 5000 networks: @@ -317,8 +317,8 @@ services: PATREON_CLIENT_ID: "" PATREON_CLIENT_SECRET: "" volumes: - - ./bases:/app/bases - - ./components:/app/components + - ./bases:/project/bases + - ./components:/project/components ports: - 5000 networks: @@ -336,6 +336,7 @@ services: context: . dockerfile: ./projects/api_ml/Dockerfile target: dev + # command: ["sleep", "infinity"] env_file: - .env environment: diff --git a/projects/api_ml/Dockerfile b/projects/api_ml/Dockerfile index a261879..7cc294a 100644 --- a/projects/api_ml/Dockerfile +++ b/projects/api_ml/Dockerfile @@ -3,7 +3,6 @@ # ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base -# Python optimizations ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 @@ -15,16 +14,17 @@ WORKDIR /project # ------------------------------------------------------------ FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ - -WORKDIR /project - -COPY ./projects/api_ml ./projects/api_ml +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv COPY ./bases ./bases COPY ./components ./components +COPY ./projects/api_ml ./projects/api_ml +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /project/projects/api_ml RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/api_ml + uv sync --frozen --no-dev # ------------------------------------------------------------ @@ -32,20 +32,21 @@ RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ # ------------------------------------------------------------ FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ - -WORKDIR /project +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ -ENV PATH="/project/.venv/bin:$PATH" ENV PYTHONPATH="/project" -COPY ./projects/api_ml ./projects/api_ml COPY ./bases ./bases COPY ./components ./components +COPY ./projects/api_ml ./projects/api_ml +COPY workspace.toml workspace.toml + +WORKDIR /project/projects/api_ml RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --dev --project ./projects/api_ml \ - && cp -r projects/api_ml/.venv/ .venv/ + uv sync --dev + +ENV PATH="/project/projects/api_ml/.venv/bin:$PATH" CMD ["uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] @@ -53,19 +54,25 @@ CMD ["uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--p # ------------------------------------------------------------ # Prod: minimal, secure, venv-only runtime # ------------------------------------------------------------ -FROM base AS prod +FROM python:3.12-slim-bookworm AS prod -WORKDIR /project - -# Create a secure user +# Non-root user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /project --no-create-home --disabled-password --uid 1000 appuser + adduser --system --ingroup appuser \ + --uid 1000 --disabled-password \ + --no-create-home appuser -COPY --from=builder --chown=appuser /project/projects/api_ml/.venv /project/.venv +# SAME PATH as builder +WORKDIR /project/projects/api_ml -ENV PATH="/project/.venv/bin:$PATH" -ENV PYTHONPATH="/project" +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /project/projects/api_ml/.venv \ + /project/projects/api_ml/.venv + +ENV PATH="/project/projects/api_ml/.venv/bin:$PATH" USER appuser -CMD ["python3", "-m", "uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] +CMD ["uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] diff --git a/projects/api_ml/Dockerfile.bak b/projects/api_ml/Dockerfile.bak deleted file mode 100644 index 6e1a4ed..0000000 --- a/projects/api_ml/Dockerfile.bak +++ /dev/null @@ -1,56 +0,0 @@ -FROM python:3.12-slim-bookworm AS base - -# Python optimizations -ENV PYTHONUNBUFFERED=1 -ENV UV_COMPILE_BYTECODE=1 - -WORKDIR /app - -FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv /bin/ - -WORKDIR /app - -COPY ./projects/api_ml ./projects/api_ml -COPY ./bases ./bases -COPY ./components ./components - -RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/api_ml - -FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv uvx/ /bin/ -COPY --from=builder /app/projects/api_ml/.venv /app/.venv - -WORKDIR /app - -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" - -COPY ./projects/api_ml ./projects/api_ml -COPY ./bases ./bases -COPY ./components ./components - -# this installs dev dependencies -RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --project ./projects/api_ml \ - && cp -r projects/api_ml/.venv/ .venv/ - -CMD ["uvicorn", "bot_detector.api_ml.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] - -FROM base AS prod - -WORKDIR /app - -# Create a secure user -RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser - -COPY --from=builder --chown=appuser /app/projects/api_ml/.venv /app/.venv - -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" - -USER appuser - -CMD ["python3", "-m", "uvicorn", "bot_detector.api_ml.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] \ No newline at end of file diff --git a/projects/api_public/Dockerfile b/projects/api_public/Dockerfile index d25ed6a..8185200 100644 --- a/projects/api_public/Dockerfile +++ b/projects/api_public/Dockerfile @@ -3,7 +3,6 @@ # ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base -# Python optimizations ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 @@ -15,16 +14,17 @@ WORKDIR /project # ------------------------------------------------------------ FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ - -WORKDIR /project - -COPY ./projects/api_public ./projects/api_public +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv COPY ./bases ./bases COPY ./components ./components +COPY ./projects/api_public ./projects/api_public +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /project/projects/api_public RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/api_public + uv sync --frozen --no-dev # ------------------------------------------------------------ @@ -32,20 +32,21 @@ RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ # ------------------------------------------------------------ FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ - -WORKDIR /project +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ -ENV PATH="/project/.venv/bin:$PATH" ENV PYTHONPATH="/project" -COPY ./projects/api_public ./projects/api_public COPY ./bases ./bases COPY ./components ./components +COPY ./projects/api_public ./projects/api_public +COPY workspace.toml workspace.toml + +WORKDIR /project/projects/api_public RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --dev --project ./projects/api_public \ - && cp -r projects/api_public/.venv/ .venv/ + uv sync --dev + +ENV PATH="/project/projects/api_public/.venv/bin:$PATH" CMD ["uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] @@ -53,19 +54,25 @@ CMD ["uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0. # ------------------------------------------------------------ # Prod: minimal, secure, venv-only runtime # ------------------------------------------------------------ -FROM base AS prod +FROM python:3.12-slim-bookworm AS prod -WORKDIR /project - -# Create a secure user +# Non-root user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /project --no-create-home --disabled-password --uid 1000 appuser + adduser --system --ingroup appuser \ + --uid 1000 --disabled-password \ + --no-create-home appuser -COPY --from=builder --chown=appuser /project/projects/api_public/.venv /project/.venv +# SAME PATH as builder +WORKDIR /project/projects/api_public -ENV PATH="/project/.venv/bin:$PATH" -ENV PYTHONPATH="/project" +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /project/projects/api_public/.venv \ + /project/projects/api_public/.venv + +ENV PATH="/project/projects/api_public/.venv/bin:$PATH" USER appuser -CMD ["python3", "-m", "uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] +CMD ["uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] diff --git a/projects/api_public/Dockerfile.bak b/projects/api_public/Dockerfile.bak deleted file mode 100644 index ece9e6b..0000000 --- a/projects/api_public/Dockerfile.bak +++ /dev/null @@ -1,57 +0,0 @@ -FROM python:3.12-slim-bookworm AS base - -# Python optimizations -ENV PYTHONUNBUFFERED=1 -ENV UV_COMPILE_BYTECODE=1 - -WORKDIR /app - -FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv /bin/ - -WORKDIR /app - -COPY ./projects/api_public ./projects/api_public -COPY ./bases ./bases -COPY ./components ./components - -RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/api_public - -FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv uvx/ /bin/ - -WORKDIR /app - -COPY --from=builder /app/projects/api_public/.venv /app/.venv - -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" - -COPY ./projects/api_public ./projects/api_public -COPY ./bases ./bases -COPY ./components ./components - -# this installs dev dependencies -RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --project ./projects/api_public \ - && cp -r projects/api_public/.venv/ .venv/ - -CMD ["uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] - -FROM base AS prod - -WORKDIR /app - -# Create a secure user -RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser - -COPY --from=builder --chown=appuser /app/projects/api_public/.venv /app/.venv - -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" - -USER appuser - -CMD ["python3", "-m", "uvicorn", "bot_detector.api_public.src.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] \ No newline at end of file diff --git a/projects/hiscore_scraper/Dockerfile b/projects/hiscore_scraper/Dockerfile index 50309d3..85f35a5 100644 --- a/projects/hiscore_scraper/Dockerfile +++ b/projects/hiscore_scraper/Dockerfile @@ -3,8 +3,8 @@ # ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base -ENV PYTHONUNBUFFERED=1 \ - UV_COMPILE_BYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV UV_COMPILE_BYTECODE=1 WORKDIR /project @@ -14,13 +14,12 @@ WORKDIR /project # ------------------------------------------------------------ FROM base AS builder -# uv COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv - -# Polylith workspace COPY ./bases ./bases COPY ./components ./components -COPY ./projects ./projects +COPY ./projects/hiscore_scraper/Dockerfile ./projects/hiscore_scraper/Dockerfile +COPY ./projects/hiscore_scraper/pyproject.toml ./projects/hiscore_scraper/pyproject.toml +COPY ./projects/hiscore_scraper/uv.lock ./projects/hiscore_scraper/uv.lock COPY workspace.toml workspace.toml # IMPORTANT: venv path is fixed here @@ -29,7 +28,6 @@ WORKDIR /project/projects/hiscore_scraper RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ uv sync --frozen --no-dev - # ------------------------------------------------------------ # Dev: full workspace + dev deps (own venv) # ------------------------------------------------------------ @@ -41,7 +39,9 @@ ENV PYTHONPATH="/project" COPY ./bases ./bases COPY ./components ./components -COPY ./projects ./projects +COPY ./projects/hiscore_scraper/Dockerfile ./projects/hiscore_scraper/Dockerfile +COPY ./projects/hiscore_scraper/pyproject.toml ./projects/hiscore_scraper/pyproject.toml +COPY ./projects/hiscore_scraper/uv.lock ./projects/hiscore_scraper/uv.lock COPY workspace.toml workspace.toml WORKDIR /project/projects/hiscore_scraper @@ -57,12 +57,12 @@ CMD ["hiscore_scraper"] # ------------------------------------------------------------ # Prod: minimal, secure, venv-only runtime # ------------------------------------------------------------ -FROM python:3.12-slim-bookworm AS prod +FROM base AS prod # Non-root user RUN addgroup --system appuser && \ adduser --system --ingroup appuser \ - --uid 5678 --disabled-password \ + --uid 1000 --disabled-password \ --no-create-home appuser # SAME PATH as builder diff --git a/projects/hiscore_scraper/Dockerfile.bak b/projects/hiscore_scraper/Dockerfile.bak deleted file mode 100644 index bc1683f..0000000 --- a/projects/hiscore_scraper/Dockerfile.bak +++ /dev/null @@ -1,81 +0,0 @@ -# ------------------------------------------------------------ -# Base (shared env only, no filesystem assumptions) -# ------------------------------------------------------------ -FROM python:3.12-slim-bookworm AS base - -ENV PYTHONUNBUFFERED=1 \ - UV_COMPILE_BYTECODE=1 - -WORKDIR /app - - -# ------------------------------------------------------------ -# Builder: runtime-only venv (path is FINAL) -# ------------------------------------------------------------ -FROM base AS builder - -# uv -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv - -# Polylith workspace -COPY ./bases ./bases -COPY ./components ./components -COPY ./projects ./projects -COPY workspace.toml workspace.toml - -# IMPORTANT: venv path is fixed here -WORKDIR /app/projects/hiscore_scraper - -RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev - - -# ------------------------------------------------------------ -# Dev: full workspace + dev deps (own venv) -# ------------------------------------------------------------ -FROM base AS dev - -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ - -ENV PYTHONPATH="/app" - -COPY ./bases ./bases -COPY ./components ./components -COPY ./projects ./projects -COPY workspace.toml workspace.toml - -WORKDIR /app/projects/hiscore_scraper - -RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --dev - -ENV PATH="/app/projects/hiscore_scraper/.venv/bin:$PATH" - -CMD ["hiscore_scraper"] - - -# ------------------------------------------------------------ -# Prod: minimal, secure, venv-only runtime -# ------------------------------------------------------------ -FROM python:3.12-slim-bookworm AS prod - -# Non-root user -RUN addgroup --system appuser && \ - adduser --system --ingroup appuser \ - --uid 5678 --disabled-password \ - --no-create-home appuser - -# SAME PATH as builder -WORKDIR /app/projects/hiscore_scraper - -# Copy sealed venv (no relocation!) -COPY --from=builder \ - --chown=appuser:appuser \ - /app/projects/hiscore_scraper/.venv \ - /app/projects/hiscore_scraper/.venv - -ENV PATH="/app/projects/hiscore_scraper/.venv/bin:$PATH" - -USER appuser - -CMD ["hiscore_scraper"] diff --git a/projects/job_hs_migration_v3/Dockerfile b/projects/job_hs_migration_v3/Dockerfile index 24cf61d..f4cad12 100644 --- a/projects/job_hs_migration_v3/Dockerfile +++ b/projects/job_hs_migration_v3/Dockerfile @@ -1,55 +1,82 @@ +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base -# Python optimizations ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 -WORKDIR /app +WORKDIR /project -FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ -WORKDIR /app +# ------------------------------------------------------------ +# Builder: production dependencies only +# ------------------------------------------------------------ +FROM base AS builder -COPY ./projects/job_hs_migration_v3 ./projects/job_hs_migration_v3 +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv COPY ./bases ./bases COPY ./components ./components +COPY ./projects/job_hs_migration_v3/Dockerfile ./projects/job_hs_migration_v3/Dockerfile +COPY ./projects/job_hs_migration_v3/pyproject.toml ./projects/job_hs_migration_v3/pyproject.toml +COPY ./projects/job_hs_migration_v3/uv.lock ./projects/job_hs_migration_v3/uv.lock +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /project/projects/job_hs_migration_v3 RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/job_hs_migration_v3 + uv sync --frozen --no-dev + +# ------------------------------------------------------------ +# Dev: development environment with dev dependencies +# ------------------------------------------------------------ FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ -COPY --from=builder /app/projects/job_hs_migration_v3/.venv /app/.venv -WORKDIR /app +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PYTHONPATH="/project" -COPY ./projects/job_hs_migration_v3 ./projects/job_hs_migration_v3 COPY ./bases ./bases COPY ./components ./components +COPY ./projects/job_hs_migration_v3/Dockerfile ./projects/job_hs_migration_v3/Dockerfile +COPY ./projects/job_hs_migration_v3/pyproject.toml ./projects/job_hs_migration_v3/pyproject.toml +COPY ./projects/job_hs_migration_v3/uv.lock ./projects/job_hs_migration_v3/uv.lock +COPY workspace.toml workspace.toml + +WORKDIR /project/projects/job_hs_migration_v3 RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --dev --project ./projects/job_hs_migration_v3 \ - && cp -r projects/job_hs_migration_v3/.venv/ .venv/ + uv sync --dev + +ENV PATH="/project/projects/job_hs_migration_v3/.venv/bin:$PATH" -CMD [".venv/bin/job_hs_migration_v3"] +CMD ["job_hs_migration_v3"] -FROM base AS prod -WORKDIR /app +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS prod -# Create a secure user +# Non-root user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + adduser --system --ingroup appuser \ + --uid 1000 --disabled-password \ + --no-create-home appuser + +# SAME PATH as builder +WORKDIR /project/projects/job_hs_migration_v3 -COPY --from=builder --chown=appuser /app/projects/job_hs_migration_v3/.venv /app/.venv +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /project/projects/job_hs_migration_v3/.venv \ + /project/projects/job_hs_migration_v3/.venv -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/projects/job_hs_migration_v3/.venv/bin:$PATH" USER appuser -CMD [".venv/bin/job_hs_migration_v3"] +CMD ["job_hs_migration_v3"] diff --git a/projects/job_hs_migration_v3/Dockerfile.bak b/projects/job_hs_migration_v3/Dockerfile.bak deleted file mode 100644 index a2d128b..0000000 --- a/projects/job_hs_migration_v3/Dockerfile.bak +++ /dev/null @@ -1,30 +0,0 @@ -FROM python:3.12-slim-bookworm AS builder - -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ - -# Set the working directory for the build stage -WORKDIR /app - -# Copy only necessary files to run the projects -COPY ./bases ./bases -COPY ./components ./components -COPY ./projects ./projects - -WORKDIR /app/projects/job_hs_migration_v3 - -# RUN uv build -RUN uv sync --frozen --no-editable - -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production - -RUN adduser -u 5678 --disabled-password --gecos "" appuser - -WORKDIR /app/projects/job_hs_migration_v3 - -COPY --from=builder --chown=appuser /app/projects/job_hs_migration_v3/.venv /app/projects/job_hs_migration_v3/.venv - -USER appuser - -CMD [".venv/bin/job_hs_migration_v3"] diff --git a/projects/job_prune_hs_data/Dockerfile b/projects/job_prune_hs_data/Dockerfile index aef676c..930ca88 100644 --- a/projects/job_prune_hs_data/Dockerfile +++ b/projects/job_prune_hs_data/Dockerfile @@ -1,55 +1,82 @@ +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base -# Python optimizations ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 -WORKDIR /app +WORKDIR /project -FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ -WORKDIR /app +# ------------------------------------------------------------ +# Builder: production dependencies only +# ------------------------------------------------------------ +FROM base AS builder -COPY ./projects/job_prune_hs_data ./projects/job_prune_hs_data +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv COPY ./bases ./bases COPY ./components ./components +COPY ./projects/job_prune_hs_data/Dockerfile ./projects/job_prune_hs_data/Dockerfile +COPY ./projects/job_prune_hs_data/pyproject.toml ./projects/job_prune_hs_data/pyproject.toml +COPY ./projects/job_prune_hs_data/uv.lock ./projects/job_prune_hs_data/uv.lock +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /project/projects/job_prune_hs_data RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/job_prune_hs_data + uv sync --frozen --no-dev + +# ------------------------------------------------------------ +# Dev: development environment with dev dependencies +# ------------------------------------------------------------ FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ -COPY --from=builder /app/projects/job_prune_hs_data/.venv /app/.venv -WORKDIR /app +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PYTHONPATH="/project" -COPY ./projects/job_prune_hs_data ./projects/job_prune_hs_data COPY ./bases ./bases COPY ./components ./components +COPY ./projects/job_prune_hs_data/Dockerfile ./projects/job_prune_hs_data/Dockerfile +COPY ./projects/job_prune_hs_data/pyproject.toml ./projects/job_prune_hs_data/pyproject.toml +COPY ./projects/job_prune_hs_data/uv.lock ./projects/job_prune_hs_data/uv.lock +COPY workspace.toml workspace.toml + +WORKDIR /project/projects/job_prune_hs_data RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --dev --project ./projects/job_prune_hs_data \ - && cp -r projects/job_prune_hs_data/.venv/ .venv/ + uv sync --dev + +ENV PATH="/project/projects/job_prune_hs_data/.venv/bin:$PATH" -CMD [".venv/bin/job_prune_hs_data"] +CMD ["job_prune_hs_data"] -FROM base AS prod -WORKDIR /app +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS prod -# Create a secure user +# Non-root user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + adduser --system --ingroup appuser \ + --uid 1000 --disabled-password \ + --no-create-home appuser + +# SAME PATH as builder +WORKDIR /project/projects/job_prune_hs_data -COPY --from=builder --chown=appuser /app/projects/job_prune_hs_data/.venv /app/.venv +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /project/projects/job_prune_hs_data/.venv \ + /project/projects/job_prune_hs_data/.venv -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/projects/job_prune_hs_data/.venv/bin:$PATH" USER appuser -CMD [".venv/bin/job_prune_hs_data"] +CMD ["job_prune_hs_data"] diff --git a/projects/job_prune_hs_data/Dockerfile.bak b/projects/job_prune_hs_data/Dockerfile.bak deleted file mode 100644 index 6be8702..0000000 --- a/projects/job_prune_hs_data/Dockerfile.bak +++ /dev/null @@ -1,30 +0,0 @@ -FROM python:3.12-slim-bookworm AS builder - -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ - -# Set the working directory for the build stage -WORKDIR /app - -# Copy only necessary files to run the projects -COPY ./bases ./bases -COPY ./components ./components -COPY ./projects ./projects - -WORKDIR /app/projects/job_prune_hs_data - -# RUN uv build -RUN uv sync --frozen --no-editable - -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production - -RUN adduser -u 5678 --disabled-password --gecos "" appuser - -WORKDIR /app/projects/job_prune_hs_data - -COPY --from=builder --chown=appuser /app/projects/job_prune_hs_data/.venv /app/projects/job_prune_hs_data/.venv - -USER appuser - -CMD [".venv/bin/job_prune_hs_data"] diff --git a/projects/runemetrics_scraper/Dockerfile b/projects/runemetrics_scraper/Dockerfile index 68792fa..eab791b 100644 --- a/projects/runemetrics_scraper/Dockerfile +++ b/projects/runemetrics_scraper/Dockerfile @@ -1,55 +1,82 @@ +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base -# Python optimizations ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 -WORKDIR /app +WORKDIR /project -FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ -WORKDIR /app +# ------------------------------------------------------------ +# Builder: production dependencies only +# ------------------------------------------------------------ +FROM base AS builder -COPY ./projects/runemetrics_scraper ./projects/runemetrics_scraper +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv COPY ./bases ./bases COPY ./components ./components +COPY ./projects/runemetrics_scraper/Dockerfile ./projects/runemetrics_scraper/Dockerfile +COPY ./projects/runemetrics_scraper/pyproject.toml ./projects/runemetrics_scraper/pyproject.toml +COPY ./projects/runemetrics_scraper/uv.lock ./projects/runemetrics_scraper/uv.lock +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /project/projects/runemetrics_scraper RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/runemetrics_scraper + uv sync --frozen --no-dev + +# ------------------------------------------------------------ +# Dev: development environment with dev dependencies +# ------------------------------------------------------------ FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ -COPY --from=builder /app/projects/runemetrics_scraper/.venv /app/.venv -WORKDIR /app +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PYTHONPATH="/project" -COPY ./projects/runemetrics_scraper ./projects/runemetrics_scraper COPY ./bases ./bases COPY ./components ./components +COPY ./projects/runemetrics_scraper/Dockerfile ./projects/runemetrics_scraper/Dockerfile +COPY ./projects/runemetrics_scraper/pyproject.toml ./projects/runemetrics_scraper/pyproject.toml +COPY ./projects/runemetrics_scraper/uv.lock ./projects/runemetrics_scraper/uv.lock +COPY workspace.toml workspace.toml + +WORKDIR /project/projects/runemetrics_scraper RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --dev --project ./projects/runemetrics_scraper \ - && cp -r projects/runemetrics_scraper/.venv/ .venv/ + uv sync --dev + +ENV PATH="/project/projects/runemetrics_scraper/.venv/bin:$PATH" -CMD [".venv/bin/runemetrics_scraper"] +CMD ["runemetrics_scraper"] -FROM base AS prod -WORKDIR /app +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS prod -# Create a secure user +# Non-root user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + adduser --system --ingroup appuser \ + --uid 1000 --disabled-password \ + --no-create-home appuser + +# SAME PATH as builder +WORKDIR /project/projects/runemetrics_scraper -COPY --from=builder --chown=appuser /app/projects/runemetrics_scraper/.venv /app/.venv +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /project/projects/runemetrics_scraper/.venv \ + /project/projects/runemetrics_scraper/.venv -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/projects/runemetrics_scraper/.venv/bin:$PATH" USER appuser -CMD [".venv/bin/runemetrics_scraper"] +CMD ["runemetrics_scraper"] diff --git a/projects/runemetrics_scraper/Dockerfile.bak b/projects/runemetrics_scraper/Dockerfile.bak deleted file mode 100644 index 2b14bd8..0000000 --- a/projects/runemetrics_scraper/Dockerfile.bak +++ /dev/null @@ -1,30 +0,0 @@ -FROM python:3.12-slim-bookworm AS builder - -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ - -# Set the working directory for the build stage -WORKDIR /app - -# Copy only necessary files to run the projects -COPY ./bases ./bases -COPY ./components ./components -COPY ./projects ./projects - -WORKDIR /app/projects/runemetrics_scraper - -# RUN uv build -RUN uv sync --frozen --no-editable - -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production - -RUN adduser -u 5678 --disabled-password --gecos "" appuser - -WORKDIR /app/projects/runemetrics_scraper - -COPY --from=builder --chown=appuser /app/projects/runemetrics_scraper/.venv /app/projects/runemetrics_scraper/.venv - -USER appuser - -CMD [".venv/bin/runemetrics_scraper"] diff --git a/projects/scrape_task_producer/Dockerfile b/projects/scrape_task_producer/Dockerfile index 4ca2b77..e82edab 100644 --- a/projects/scrape_task_producer/Dockerfile +++ b/projects/scrape_task_producer/Dockerfile @@ -1,55 +1,82 @@ +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base -# Python optimizations ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 -WORKDIR /app +WORKDIR /project -FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ -WORKDIR /app +# ------------------------------------------------------------ +# Builder: production dependencies only +# ------------------------------------------------------------ +FROM base AS builder -COPY ./projects/scrape_task_producer ./projects/scrape_task_producer +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv COPY ./bases ./bases COPY ./components ./components +COPY ./projects/scrape_task_producer/Dockerfile ./projects/scrape_task_producer/Dockerfile +COPY ./projects/scrape_task_producer/pyproject.toml ./projects/scrape_task_producer/pyproject.toml +COPY ./projects/scrape_task_producer/uv.lock ./projects/scrape_task_producer/uv.lock +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /project/projects/scrape_task_producer RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/scrape_task_producer + uv sync --frozen --no-dev + +# ------------------------------------------------------------ +# Dev: development environment with dev dependencies +# ------------------------------------------------------------ FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ -COPY --from=builder /app/projects/scrape_task_producer/.venv /app/.venv -WORKDIR /app +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PYTHONPATH="/project" -COPY ./projects/scrape_task_producer ./projects/scrape_task_producer COPY ./bases ./bases COPY ./components ./components +COPY ./projects/scrape_task_producer/Dockerfile ./projects/scrape_task_producer/Dockerfile +COPY ./projects/scrape_task_producer/pyproject.toml ./projects/scrape_task_producer/pyproject.toml +COPY ./projects/scrape_task_producer/uv.lock ./projects/scrape_task_producer/uv.lock +COPY workspace.toml workspace.toml + +WORKDIR /project/projects/scrape_task_producer RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --dev --project ./projects/scrape_task_producer \ - && cp -r projects/scrape_task_producer/.venv/ .venv/ + uv sync --dev + +ENV PATH="/project/projects/scrape_task_producer/.venv/bin:$PATH" -CMD [".venv/bin/scrape_task_producer"] +CMD ["scrape_task_producer"] -FROM base AS prod -WORKDIR /app +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS prod -# Create a secure user +# Non-root user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + adduser --system --ingroup appuser \ + --uid 1000 --disabled-password \ + --no-create-home appuser + +# SAME PATH as builder +WORKDIR /project/projects/scrape_task_producer -COPY --from=builder --chown=appuser /app/projects/scrape_task_producer/.venv /app/.venv +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /project/projects/scrape_task_producer/.venv \ + /project/projects/scrape_task_producer/.venv -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/projects/scrape_task_producer/.venv/bin:$PATH" USER appuser -CMD [".venv/bin/scrape_task_producer"] +CMD ["scrape_task_producer"] diff --git a/projects/scrape_task_producer/Dockerfile.bak b/projects/scrape_task_producer/Dockerfile.bak deleted file mode 100644 index cf5bbc0..0000000 --- a/projects/scrape_task_producer/Dockerfile.bak +++ /dev/null @@ -1,30 +0,0 @@ -FROM python:3.12-slim-bookworm AS builder - -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ - -# Set the working directory for the build stage -WORKDIR /app - -# Copy only necessary files to run the projects -COPY ./bases ./bases -COPY ./components ./components -COPY ./projects ./projects - -WORKDIR /app/projects/scrape_task_producer - -# RUN uv build -RUN uv sync --frozen --no-editable - -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production - -RUN adduser -u 5678 --disabled-password --gecos "" appuser - -WORKDIR /app/projects/scrape_task_producer - -COPY --from=builder --chown=appuser /app/projects/scrape_task_producer/.venv /app/projects/scrape_task_producer/.venv - -USER appuser - -CMD [".venv/bin/scrape_task_producer"] diff --git a/projects/website/Dockerfile b/projects/website/Dockerfile index 73d01ce..83e3358 100644 --- a/projects/website/Dockerfile +++ b/projects/website/Dockerfile @@ -1,55 +1,82 @@ +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base -# Python optimizations ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 -WORKDIR /app +WORKDIR /project -FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ -WORKDIR /app +# ------------------------------------------------------------ +# Builder: production dependencies only +# ------------------------------------------------------------ +FROM base AS builder -COPY ./projects/website ./projects/website +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv COPY ./bases ./bases COPY ./components ./components +COPY ./projects/website/Dockerfile ./projects/website/Dockerfile +COPY ./projects/website/pyproject.toml ./projects/website/pyproject.toml +COPY ./projects/website/uv.lock ./projects/website/uv.lock +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /project/projects/website RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/website + uv sync --frozen --no-dev + +# ------------------------------------------------------------ +# Dev: development environment with dev dependencies +# ------------------------------------------------------------ FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ -COPY --from=builder /app/projects/website/.venv /app/.venv -WORKDIR /app +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PYTHONPATH="/project" -COPY ./projects/website ./projects/website COPY ./bases ./bases COPY ./components ./components +COPY ./projects/website/Dockerfile ./projects/website/Dockerfile +COPY ./projects/website/pyproject.toml ./projects/website/pyproject.toml +COPY ./projects/website/uv.lock ./projects/website/uv.lock +COPY workspace.toml workspace.toml + +WORKDIR /project/projects/website RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --dev --project ./projects/website \ - && cp -r projects/website/.venv/ .venv/ + uv sync --dev + +ENV PATH="/project/projects/website/.venv/bin:$PATH" CMD ["uvicorn", "bot_detector.website.core.server:app", "--host", "0.0.0.0", "--port", "5000", "--reload"] -FROM base AS prod -WORKDIR /app +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS prod -# Create a secure user +# Non-root user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + adduser --system --ingroup appuser \ + --uid 1000 --disabled-password \ + --no-create-home appuser + +# SAME PATH as builder +WORKDIR /project/projects/website -COPY --from=builder --chown=appuser /app/projects/website/.venv /app/.venv +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /project/projects/website/.venv \ + /project/projects/website/.venv -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/projects/website/.venv/bin:$PATH" USER appuser -CMD [".venv/bin/uvicorn", "bot_detector.website.core.server:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] +CMD ["uvicorn", "bot_detector.website.core.server:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] diff --git a/projects/website/Dockerfile.bak b/projects/website/Dockerfile.bak deleted file mode 100644 index 211b76e..0000000 --- a/projects/website/Dockerfile.bak +++ /dev/null @@ -1,30 +0,0 @@ -FROM python:3.12-slim-bookworm AS builder - -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.4 /uv /uvx /bin/ - -# set the working directory -WORKDIR /app - -# Copy only necessary files to run the projects -COPY ./bases ./bases -COPY ./components ./components -COPY ./projects ./projects - -WORKDIR /app/projects/website - -# install dependencies via RUN uv build -RUN uv sync --frozen --no-editable - -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production - -# Creates a non-root user with an explicit UID and adds permission to access the /project folder -RUN adduser -u 5678 --disabled-password --gecos "" appuser - -WORKDIR /app/projects/website -COPY --from=builder --chown=appuser /app/projects/website/.venv /app/projects/website/.venv - -USER appuser - -CMD [".venv/bin/uvicorn", "bot_detector.website.core.server:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "5000", "--log-level", "warning"] \ No newline at end of file diff --git a/projects/worker_hiscore/Dockerfile b/projects/worker_hiscore/Dockerfile index 2efe4c8..ab68056 100644 --- a/projects/worker_hiscore/Dockerfile +++ b/projects/worker_hiscore/Dockerfile @@ -1,55 +1,82 @@ +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base -# Python optimizations ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 -WORKDIR /app +WORKDIR /project -FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ -WORKDIR /app +# ------------------------------------------------------------ +# Builder: production dependencies only +# ------------------------------------------------------------ +FROM base AS builder -COPY ./projects/worker_hiscore ./projects/worker_hiscore +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv COPY ./bases ./bases COPY ./components ./components +COPY ./projects/worker_hiscore/Dockerfile ./projects/worker_hiscore/Dockerfile +COPY ./projects/worker_hiscore/pyproject.toml ./projects/worker_hiscore/pyproject.toml +COPY ./projects/worker_hiscore/uv.lock ./projects/worker_hiscore/uv.lock +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /project/projects/worker_hiscore RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/worker_hiscore + uv sync --frozen --no-dev + +# ------------------------------------------------------------ +# Dev: development environment with dev dependencies +# ------------------------------------------------------------ FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ -COPY --from=builder /app/projects/worker_hiscore/.venv /app/.venv -WORKDIR /app +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PYTHONPATH="/project" -COPY ./projects/worker_hiscore ./projects/worker_hiscore COPY ./bases ./bases COPY ./components ./components +COPY ./projects/worker_hiscore/Dockerfile ./projects/worker_hiscore/Dockerfile +COPY ./projects/worker_hiscore/pyproject.toml ./projects/worker_hiscore/pyproject.toml +COPY ./projects/worker_hiscore/uv.lock ./projects/worker_hiscore/uv.lock +COPY workspace.toml workspace.toml + +WORKDIR /project/projects/worker_hiscore RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --dev --project ./projects/worker_hiscore \ - && cp -r projects/worker_hiscore/.venv/ .venv/ + uv sync --dev + +ENV PATH="/project/projects/worker_hiscore/.venv/bin:$PATH" -CMD [".venv/bin/worker_hiscore"] +CMD ["worker_hiscore"] -FROM base AS prod -WORKDIR /app +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS prod -# Create a secure user +# Non-root user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + adduser --system --ingroup appuser \ + --uid 1000 --disabled-password \ + --no-create-home appuser + +# SAME PATH as builder +WORKDIR /project/projects/worker_hiscore -COPY --from=builder --chown=appuser /app/projects/worker_hiscore/.venv /app/.venv +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /project/projects/worker_hiscore/.venv \ + /project/projects/worker_hiscore/.venv -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/projects/worker_hiscore/.venv/bin:$PATH" USER appuser -CMD [".venv/bin/worker_hiscore"] +CMD ["worker_hiscore"] diff --git a/projects/worker_hiscore/Dockerfile.bak b/projects/worker_hiscore/Dockerfile.bak deleted file mode 100644 index 4ccbddd..0000000 --- a/projects/worker_hiscore/Dockerfile.bak +++ /dev/null @@ -1,30 +0,0 @@ -FROM python:3.12-slim-bookworm AS builder - -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ - -# Set the working directory for the build stage -WORKDIR /app - -# Copy only necessary files to run the projects -COPY ./bases ./bases -COPY ./components ./components -COPY ./projects ./projects - -WORKDIR /app/projects/worker_hiscore - -# RUN uv build -RUN uv sync --frozen --no-editable - -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production - -RUN adduser -u 5678 --disabled-password --gecos "" appuser - -WORKDIR /app/projects/worker_hiscore - -COPY --from=builder --chown=appuser /app/projects/worker_hiscore/.venv /app/projects/worker_hiscore/.venv - -USER appuser - -CMD [".venv/bin/worker_hiscore"] diff --git a/projects/worker_ml/Dockerfile b/projects/worker_ml/Dockerfile index 0013e4a..bcfeebe 100644 --- a/projects/worker_ml/Dockerfile +++ b/projects/worker_ml/Dockerfile @@ -1,55 +1,82 @@ +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base -# Python optimizations ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 -WORKDIR /app +WORKDIR /project -FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ -WORKDIR /app +# ------------------------------------------------------------ +# Builder: production dependencies only +# ------------------------------------------------------------ +FROM base AS builder -COPY ./projects/worker_ml ./projects/worker_ml +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv COPY ./bases ./bases COPY ./components ./components +COPY ./projects/worker_ml/Dockerfile ./projects/worker_ml/Dockerfile +COPY ./projects/worker_ml/pyproject.toml ./projects/worker_ml/pyproject.toml +COPY ./projects/worker_ml/uv.lock ./projects/worker_ml/uv.lock +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /project/projects/worker_ml RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/worker_ml + uv sync --frozen --no-dev + +# ------------------------------------------------------------ +# Dev: development environment with dev dependencies +# ------------------------------------------------------------ FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ -COPY --from=builder /app/projects/worker_ml/.venv /app/.venv -WORKDIR /app +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PYTHONPATH="/project" -COPY ./projects/worker_ml ./projects/worker_ml COPY ./bases ./bases COPY ./components ./components +COPY ./projects/worker_ml/Dockerfile ./projects/worker_ml/Dockerfile +COPY ./projects/worker_ml/pyproject.toml ./projects/worker_ml/pyproject.toml +COPY ./projects/worker_ml/uv.lock ./projects/worker_ml/uv.lock +COPY workspace.toml workspace.toml + +WORKDIR /project/projects/worker_ml RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --dev --project ./projects/worker_ml \ - && cp -r projects/worker_ml/.venv/ .venv/ + uv sync --dev + +ENV PATH="/project/projects/worker_ml/.venv/bin:$PATH" -CMD [".venv/bin/worker_ml"] +CMD ["worker_ml"] -FROM base AS prod -WORKDIR /app +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS prod -# Create a secure user +# Non-root user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + adduser --system --ingroup appuser \ + --uid 1000 --disabled-password \ + --no-create-home appuser + +# SAME PATH as builder +WORKDIR /project/projects/worker_ml -COPY --from=builder --chown=appuser /app/projects/worker_ml/.venv /app/.venv +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /project/projects/worker_ml/.venv \ + /project/projects/worker_ml/.venv -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/projects/worker_ml/.venv/bin:$PATH" USER appuser -CMD [".venv/bin/worker_ml"] +CMD ["worker_ml"] diff --git a/projects/worker_ml/Dockerfile.bak b/projects/worker_ml/Dockerfile.bak deleted file mode 100644 index 648d1ed..0000000 --- a/projects/worker_ml/Dockerfile.bak +++ /dev/null @@ -1,30 +0,0 @@ -FROM python:3.12-slim-bookworm AS builder - -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ - -# Set the working directory for the build stage -WORKDIR /app - -# Copy only necessary files to run the projects -COPY ./bases ./bases -COPY ./components ./components -COPY ./projects ./projects - -WORKDIR /app/projects/worker_ml - -# RUN uv build -RUN uv sync --frozen --no-editable - -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production - -RUN adduser -u 5678 --disabled-password --gecos "" appuser - -WORKDIR /app/projects/worker_ml - -COPY --from=builder --chown=appuser /app/projects/worker_ml/.venv /app/projects/worker_ml/.venv - -USER appuser - -CMD [".venv/bin/worker_ml"] diff --git a/projects/worker_report/Dockerfile b/projects/worker_report/Dockerfile index 9c070e7..87bab27 100644 --- a/projects/worker_report/Dockerfile +++ b/projects/worker_report/Dockerfile @@ -1,55 +1,82 @@ +# ------------------------------------------------------------ +# Base (shared env only, no filesystem assumptions) +# ------------------------------------------------------------ FROM python:3.12-slim-bookworm AS base -# Python optimizations ENV PYTHONUNBUFFERED=1 ENV UV_COMPILE_BYTECODE=1 -WORKDIR /app +WORKDIR /project -FROM base AS builder -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/ -WORKDIR /app +# ------------------------------------------------------------ +# Builder: production dependencies only +# ------------------------------------------------------------ +FROM base AS builder -COPY ./projects/worker_report ./projects/worker_report +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /bin/uv COPY ./bases ./bases COPY ./components ./components +COPY ./projects/worker_report/Dockerfile ./projects/worker_report/Dockerfile +COPY ./projects/worker_report/pyproject.toml ./projects/worker_report/pyproject.toml +COPY ./projects/worker_report/uv.lock ./projects/worker_report/uv.lock +COPY workspace.toml workspace.toml + +# IMPORTANT: venv path is fixed here +WORKDIR /project/projects/worker_report RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev --project ./projects/worker_report + uv sync --frozen --no-dev + +# ------------------------------------------------------------ +# Dev: development environment with dev dependencies +# ------------------------------------------------------------ FROM base AS dev -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv uvx/ /bin/ -COPY --from=builder /app/projects/worker_report/.venv /app/.venv -WORKDIR /app +COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PYTHONPATH="/project" -COPY ./projects/worker_report ./projects/worker_report COPY ./bases ./bases COPY ./components ./components +COPY ./projects/worker_report/Dockerfile ./projects/worker_report/Dockerfile +COPY ./projects/worker_report/pyproject.toml ./projects/worker_report/pyproject.toml +COPY ./projects/worker_report/uv.lock ./projects/worker_report/uv.lock +COPY workspace.toml workspace.toml + +WORKDIR /project/projects/worker_report RUN --mount=type=cache,id=uv_cache,target=/root/.cache/uv \ - uv sync --dev --project ./projects/worker_report \ - && cp -r projects/worker_report/.venv/ .venv/ + uv sync --dev + +ENV PATH="/project/projects/worker_report/.venv/bin:$PATH" -CMD [".venv/bin/worker_report"] +CMD ["worker_report"] -FROM base AS prod -WORKDIR /app +# ------------------------------------------------------------ +# Prod: minimal, secure, venv-only runtime +# ------------------------------------------------------------ +FROM python:3.12-slim-bookworm AS prod -# Create a secure user +# Non-root user RUN addgroup --system appuser && \ - adduser --system --ingroup appuser --home /app --no-create-home --disabled-password --uid 5678 appuser + adduser --system --ingroup appuser \ + --uid 1000 --disabled-password \ + --no-create-home appuser + +# SAME PATH as builder +WORKDIR /project/projects/worker_report -COPY --from=builder --chown=appuser /app/projects/worker_report/.venv /app/.venv +# Copy sealed venv (no relocation!) +COPY --from=builder \ + --chown=appuser:appuser \ + /project/projects/worker_report/.venv \ + /project/projects/worker_report/.venv -ENV PATH="/app/.venv/bin:$PATH" -ENV PYTHONPATH="/app" +ENV PATH="/project/projects/worker_report/.venv/bin:$PATH" USER appuser -CMD [".venv/bin/worker_report"] +CMD ["worker_report"] diff --git a/projects/worker_report/Dockerfile.bak b/projects/worker_report/Dockerfile.bak deleted file mode 100644 index 372cd31..0000000 --- a/projects/worker_report/Dockerfile.bak +++ /dev/null @@ -1,30 +0,0 @@ -FROM python:3.12-slim-bookworm AS builder - -# Copy uv from external repository -COPY --from=ghcr.io/astral-sh/uv:0.5.13 /uv /uvx /bin/ - -# Set the working directory for the build stage -WORKDIR /app - -# Copy only necessary files to run the projects -COPY ./bases ./bases -COPY ./components ./components -COPY ./projects ./projects - -WORKDIR /app/projects/worker_report - -# RUN uv build -RUN uv sync --frozen --no-editable - -# Production stage: Prepare the final production environment -FROM python:3.12-slim-bookworm AS production - -RUN adduser -u 5678 --disabled-password --gecos "" appuser - -WORKDIR /app/projects/worker_report - -COPY --from=builder --chown=appuser /app/projects/worker_report/.venv /app/projects/worker_report/.venv - -USER appuser - -CMD [".venv/bin/worker_report"] From 07e24478921b609aab085890d823a3e24f0bed07 Mon Sep 17 00:00:00 2001 From: extreme4all <> Date: Sat, 24 Jan 2026 21:42:32 +0100 Subject: [PATCH 5/5] random bug fix --- bases/bot_detector/worker_report/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bases/bot_detector/worker_report/main.py b/bases/bot_detector/worker_report/main.py index 5d66e1b..3040948 100644 --- a/bases/bot_detector/worker_report/main.py +++ b/bases/bot_detector/worker_report/main.py @@ -138,6 +138,7 @@ async def main(): ## producer report_producer = RepoReportsToInsertProducer( bootstrap_servers=b_server, + max_async_calls=100, ) # start kafka producers and consumers