diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6198714 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +.git +.gitignore +.vscode +.venv +.pytest_cache +.ruff_cache +__pycache__/ +*.py[cod] +*.db +.env +tests/ +docs/ +uploads/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c91e54b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +FROM python:3.12-slim AS builder + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + UV_LINK_MODE=copy + +WORKDIR /app + +COPY --from=ghcr.io/astral-sh/uv:0.5.24 /uv /uvx /bin/ + +COPY pyproject.toml uv.lock README.md ./ +RUN uv sync --frozen --no-dev --no-install-project + +COPY src ./src +COPY prompts ./prompts +RUN uv sync --frozen --no-dev + + +FROM python:3.12-slim AS runtime + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + PATH="/app/.venv/bin:$PATH" \ + PYTHONPATH="/app/src" \ + UPLOAD_DIR="/app/uploads" \ + PROMPT_DIR="/app/prompts" + +WORKDIR /app + +RUN groupadd --system --gid 1001 appgroup \ + && useradd --system --uid 1001 --gid appgroup --create-home appuser + +COPY --from=builder /app/.venv /app/.venv +COPY --from=builder /app/src /app/src +COPY --from=builder /app/prompts /app/prompts + +RUN mkdir -p /app/uploads /app/data \ + && chown -R appuser:appgroup /app + +USER appuser + +EXPOSE 8000 + +HEALTHCHECK --interval=30s --timeout=3s --start-period=3s --retries=3 \ + CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/healthz')" + +CMD ["uvicorn", "transcription.app:create_app", "--factory", "--host", "0.0.0.0", "--port", "8000", "--proxy-headers"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8b7f92c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,21 @@ +services: + transcription: + build: + context: . + dockerfile: Dockerfile + container_name: transcription-app + env_file: + - .env + environment: + DATABASE_URL: sqlite:////app/data/transcription.db + UPLOAD_DIR: /app/uploads + PROMPT_DIR: /app/prompts + ports: + - "8002:8000" + volumes: + - ./uploads:/app/uploads + - transcription_data:/app/data + restart: unless-stopped + +volumes: + transcription_data: