diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..14dc652 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,45 @@ +# Git +.git +.gitignore +.github + +# Python artifacts +__pycache__/ +*.py[cod] +*.pyo +*.pyd +.Python +*.egg-info/ +dist/ +build/ +*.egg + +# Virtual environments +venv/ +.venv/ +env/ +.env/ + +# IDE / editors +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS files +.DS_Store +Thumbs.db + +# Logs & temp +*.log +*.tmp + +# Test / CI +.pytest_cache/ +htmlcov/ +.coverage + +# Docs & media (optional, remove if app needs them at runtime) +README.md +media/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7f6d1b4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# Use official Python slim image for smaller size +FROM python:3.10-slim + +# Set environment variables +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 + +# Set working directory +WORKDIR /app + +# Install system dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + curl \ + git \ + && rm -rf /var/lib/apt/lists/* + +# Copy requirements first for better Docker layer caching +COPY requirements.txt . + +# Install Python dependencies +# Note: PyQt6 is excluded since we're running headless (Streamlit web UI only) +# Note: en_core_web_sm is already included in requirements.txt as a wheel download +RUN pip install --upgrade pip && \ + grep -v "^PyQt6" requirements.txt > requirements_web.txt && \ + pip install -r requirements_web.txt + +# Download additional NLTK data required by the app +RUN python -c "import nltk; nltk.download('punkt'); nltk.download('wordnet'); nltk.download('averaged_perceptron_tagger'); nltk.download('punkt_tab')" + +# Copy the application source code +COPY . . + +# Expose Streamlit's default port +EXPOSE 8501 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ + CMD curl -f http://localhost:8501/_stcore/health || exit 1 + +# Run the Streamlit app +CMD ["streamlit", "run", "main.py", \ + "--server.port=8501", \ + "--server.address=0.0.0.0", \ + "--server.headless=true", \ + "--browser.gatherUsageStats=false"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..70bde62 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,28 @@ +version: "3.9" + +services: + ai-text-humanizer: + build: + context: . + dockerfile: Dockerfile + image: ai-text-humanizer-app:latest + container_name: ai-text-humanizer + ports: + - "8501:8501" + environment: + - PYTHONUNBUFFERED=1 + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8501/_stcore/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + volumes: + # Optional: mount local code for development (comment out for production) + # - .:/app + # Persist NLTK data to avoid re-downloading on container restart + - nltk_data:/root/nltk_data + +volumes: + nltk_data: diff --git a/requirements.txt b/requirements.txt index b52a567..eff4e30 100644 Binary files a/requirements.txt and b/requirements.txt differ