diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6556c5f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +.venv +__pycache__ +*.pyc +.pytest_cache +.git +docs +data/*.csv +.env +rf_stress_model.joblib diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..2d35b7d --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,36 @@ +name: Build and publish Docker image + +on: + push: + branches: [ main ] + +permissions: + contents: read + packages: write + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push image + uses: docker/build-push-action@v4 + with: + push: true + tags: ghcr.io/${{ github.repository_owner }}/mindguard:latest + file: ./Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3d6ba42 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +FROM python:3.10-slim + +# Prevent Python from writing .pyc files and buffering stdout/stderr +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +WORKDIR /app + +# Install system deps (minimal) and Python deps +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + +# Copy project +COPY . /app + +# Expose Streamlit default port +EXPOSE 8501 + +ENV STREAMLIT_SERVER_HEADLESS=true + +# Run the Streamlit app +CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"] diff --git a/README.md b/README.md index 75f04b9..e6f88fa 100644 --- a/README.md +++ b/README.md @@ -92,3 +92,25 @@ If you rely on Gemini for richer responses, monitor your Google Cloud quota and Recommendations / result view: ![Recommendations view](assets/screenshots/recommendations_view.svg) + +Docker / container deployment +-------------------------------- +I added a Dockerfile and docker-compose configuration so you can run the Streamlit app in a container or publish the image to a container registry. + +Run locally with Docker Compose + +1. Build and run: +```bash +docker compose up --build +``` +2. Open the app at: http://localhost:8501 + +Notes: +- The container reads `GOOGLE_API_KEY` from the environment. You can provide it with `export GOOGLE_API_KEY=...` before running `docker compose up`, or create a `.env` file with that variable (do not commit secrets). +- The image exposes port 8501. + +Publish image automatically (GitHub) + +- I added a GitHub Actions workflow `.github/workflows/docker-publish.yml`. On push to `main` it builds the image and pushes it to GitHub Container Registry (GHCR) as `ghcr.io//mindguard:latest`. +- After pushing, you can deploy that container image to any hosting provider that accepts Docker images (Render, Fly.io, Railway, DigitalOcean App Platform, etc.). + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3d73b29 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +services: + mindguard: + build: . + image: mindguard:latest + ports: + - "8501:8501" + volumes: + # Mount current repo (read-only) so edits are visible during development + - ./:/app:ro + environment: + # Forward GOOGLE_API_KEY from host or .env + - GOOGLE_API_KEY=${GOOGLE_API_KEY} + restart: unless-stopped