diff --git a/README.md b/README.md index e2154eb..95966a6 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,81 @@ $ python3 sf.py inventory ls --- +## 🐳 Docker Setup + +For easy deployment and consistent environments, smallFactory can be run using Docker: + +### Quick Start with Docker Compose + +1. **Clone the repository**: + ```bash + git clone https://github.com/yourusername/smallfactory.git + cd smallfactory + ``` + +2. **Configure your environment** (optional): + ```bash + cp docker/.env.example .env + # Edit .env to set your git repository and user details + ``` + +3. **Start with docker-compose**: + ```bash + docker-compose -f docker/docker-compose.yml up -d + ``` + +4. **Access the web interface**: + Open `http://localhost:8080` in your browser + +### Configuration Options + +The Docker setup supports several configuration options via environment variables: + +- **`SF_DATAREPO_PATH`**: Path to your local data repository (default: `./data`) +- **`SF_GIT_REPO_URL`**: Git repository URL for automatic cloning (optional) +- **`SF_GIT_USER_NAME`**: Git user name for commits (default: "SmallFactory Docker") +- **`SF_GIT_USER_EMAIL`**: Git user email for commits (default: "docker@smallfactory.local") + +### Usage Scenarios + +**Scenario 1: Using an existing local git repository** +```bash +SF_DATAREPO_PATH=/path/to/your/existing/plm-repo docker-compose -f docker/docker-compose.yml up +``` + +**Scenario 2: Clone from a remote repository** +```bash +echo "SF_GIT_REPO_URL=https://github.com/yourusername/plm-data.git" > .env +docker-compose -f docker/docker-compose.yml up +``` + +**Scenario 3: Start fresh** +```bash +# Just run with defaults - creates ./data directory +docker-compose -f docker/docker-compose.yml up +# Initialize repository via web interface or CLI +``` + +### Docker Features + +The Docker container includes: +- **Production-ready web server** (Gunicorn) +- **Ollama with qwen2.5vl:3b model** for AI-powered image recognition +- **Git integration** with automatic repository setup +- **Persistent data** via volume mounts +- **Security**: Non-root user for web application + +### Data Persistence + +Your PLM data is stored outside the container in the mounted volume, so it persists when you: +- Stop/start containers +- Update the Docker image +- Recreate containers + +Simply backup your local data directory to preserve all your PLM data and git history. + +--- + ## 🧠 Philosophy Every decision in smallfactory is guided by this rule: diff --git a/docker/.env.example b/docker/.env.example new file mode 100644 index 0000000..3635966 --- /dev/null +++ b/docker/.env.example @@ -0,0 +1,11 @@ +# SmallFactory Docker Configuration + +# Path to your local data repository (will be mounted into container) +SF_DATAREPO_PATH=./data + +# Optional: Git repository URL for automatic cloning/syncing +# SF_GIT_REPO_URL=https://github.com/yourusername/your-plm-data.git + +# Git configuration for commits made from within the container +SF_GIT_USER_NAME=Your Name +SF_GIT_USER_EMAIL=your.email@example.com \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..c7a49c8 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,58 @@ +# Multi-stage build for smallfactory PLM/BOM management tool +FROM python:3.11-slim as base + +# Install system dependencies including curl for Ollama +RUN apt-get update && apt-get install -y \ + git \ + curl \ + su-exec \ + && rm -rf /var/lib/apt/lists/* + +# Install Ollama +RUN curl -fsSL https://ollama.com/install.sh | sh + +# Pre-download the vision model during build to avoid runtime download +RUN ollama serve & \ + server_pid=$! && \ + sleep 5 && \ + ollama pull qwen2.5vl:3b && \ + kill $server_pid && \ + wait + +# Set working directory +WORKDIR /app + +# Copy requirements and install Python dependencies +COPY requirements.txt ./ +COPY web/requirements.txt ./web/ +RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir -r web/requirements.txt +RUN pip install --no-cache-dir gunicorn + +# Copy application code +COPY . . + +# Copy and set permissions for entrypoint script +COPY docker-entrypoint.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + +# Create a non-root user for security (but don't switch to it yet, Ollama needs root) +RUN groupadd -r appuser && useradd -r -g appuser appuser +RUN chown -R appuser:appuser /app + +# Expose port for web interface only (Ollama is internal) +EXPOSE 8080 + +# Environment variables +ENV PYTHONPATH=/app +ENV FLASK_ENV=production +ENV SF_OLLAMA_BASE_URL=http://localhost:11434 +ENV SF_VISION_MODEL=qwen2.5vl:3b + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD python -c "import requests; requests.get('http://localhost:8080')" || exit 1 + +# Set entrypoint to start Ollama and then run Gunicorn +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["gunicorn", "--bind", "0.0.0.0:8080", "--workers", "4", "--timeout", "120", "web.app:app"] \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000..02ae22d --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3.8' + +services: + smallfactory: + build: . + ports: + - "8080:8080" + volumes: + # Mount external data repository directory + - "${SF_DATAREPO_PATH:-./data}:/app/data" + environment: + # Git repository URL (optional - for cloning/syncing) + - SF_GIT_REPO_URL=${SF_GIT_REPO_URL:-} + # Data repository path inside container + - SF_DATAREPO_PATH=/app/data + # Git configuration for commits + - SF_GIT_USER_NAME=${SF_GIT_USER_NAME:-SmallFactory Docker} + - SF_GIT_USER_EMAIL=${SF_GIT_USER_EMAIL:-docker@smallfactory.local} + restart: unless-stopped \ No newline at end of file diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh new file mode 100644 index 0000000..906925f --- /dev/null +++ b/docker/docker-entrypoint.sh @@ -0,0 +1,41 @@ +#!/bin/bash +set -e + +# Start Ollama in the background as root (required) +echo "Starting Ollama server..." +ollama serve & + +# Wait for Ollama to be ready +echo "Waiting for Ollama to be ready..." +max_attempts=15 +attempt=0 +while ! curl -s http://localhost:11434/api/tags > /dev/null; do + if [ $attempt -ge $max_attempts ]; then + echo "ERROR: Ollama failed to start within 30 seconds" + exit 1 + fi + sleep 2 + attempt=$((attempt + 1)) +done + +echo "Ollama is ready! Model ${SF_VISION_MODEL} is available." + +# Handle git repository setup +if [ ! -z "$SF_GIT_REPO_URL" ] && [ ! -d "/app/data/.git" ]; then + echo "Cloning git repository from $SF_GIT_REPO_URL..." + git clone "$SF_GIT_REPO_URL" /app/data +elif [ -d "/app/data" ] && [ ! -d "/app/data/.git" ]; then + echo "No git repository found in /app/data. You may want to initialize one or set SF_GIT_REPO_URL." +fi + +# Set git configuration if provided +if [ ! -z "$SF_GIT_USER_NAME" ] && [ ! -z "$SF_GIT_USER_EMAIL" ]; then + echo "Configuring git user..." + git config --global user.name "$SF_GIT_USER_NAME" + git config --global user.email "$SF_GIT_USER_EMAIL" +fi + +echo "Starting smallFactory web application as appuser..." +# Switch to non-root user for the web application +cd /app +exec su-exec appuser "$@" \ No newline at end of file