diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e15d70e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,17 @@ +.venv/ +.git/ +.gitignore +.ruff_cache/ +.pytest_cache/ +.idea/ +.beads/ +.claude/ +__pycache__/ +*.py[cod] +*.egg-info/ +build/ +dist/ +data/ +docs/ +tests/ +scripts/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f3156b3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# ---- Base stage: shared dependencies ---- +FROM python:3.13-slim AS base + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + UV_COMPILE_BYTECODE=1 \ + UV_LINK_MODE=copy + +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ + +WORKDIR /app + +# Install production dependencies (cached unless lock changes) +COPY pyproject.toml uv.lock ./ +RUN uv sync --frozen --no-install-project --no-dev + +# ---- Dev stage: hot-reload for local development ---- +FROM base AS dev + +# Also install dev dependencies +RUN uv sync --frozen --no-install-project + +# Source is bind-mounted at runtime via docker-compose +ENV OIDC_OP_ISSUER=http://localhost:8000 \ + OIDC_OP_DEBUG=true + +EXPOSE 8000 + +CMD ["uv", "run", "uvicorn", "fastapi_oidc_op.app:create_app", \ + "--factory", "--host", "0.0.0.0", "--port", "8000", \ + "--reload", "--reload-dir", "/app/src"] + +# ---- Prod stage: optimised image ---- +FROM base AS prod + +# Copy source + README (needed by hatchling) and install the project itself +COPY README.md ./ +COPY src/ src/ +RUN uv sync --frozen --no-dev + +ENV OIDC_OP_ISSUER=http://localhost:8000 + +EXPOSE 8000 + +CMD ["uv", "run", "uvicorn", "fastapi_oidc_op.app:create_app", \ + "--factory", "--host", "0.0.0.0", "--port", "8000", \ + "--workers", "4"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..5f0573d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,34 @@ +services: + app: + build: + context: . + target: prod + ports: + - "8000:8000" + environment: + OIDC_OP_ISSUER: "http://localhost:8000" + OIDC_OP_SESSION_SECRET: "change-me-in-production" + volumes: + - app-data:/app/data + profiles: + - prod + + app-dev: + build: + context: . + target: dev + ports: + - "8000:8000" + environment: + OIDC_OP_ISSUER: "http://localhost:8000" + OIDC_OP_DEBUG: "true" + volumes: + - ./src:/app/src + - ./pyproject.toml:/app/pyproject.toml + - dev-data:/app/data + profiles: + - dev + +volumes: + app-data: + dev-data: