diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3309913 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,50 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +venv/ +env/ +ENV/ +*.egg-info/ +dist/ +build/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Git +.git/ +.gitignore + +# Environment files (will be mounted separately) +.env + +# Documentation +README.md + +# CI/CD +.github/ + +# Claude +.claude/ + +# Instance data (will be mounted as volume) +src/app/instance/ +src/app/static/images/ +src/app/static/barcodes/ + +# Test files +*.pyc +.pytest_cache/ +.coverage +htmlcov/ + +# OS +.DS_Store +Thumbs.db diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..7fdda1f --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,35 @@ +name: Build and Push Docker Image + +on: + push: + tags: + - 'v*' # triggers only on version tags like v1.0.0, v25.04, etc. + +jobs: + build-and-push: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Extract version from tag + run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV + + - name: Build and push Docker image with two tags + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: | + mattintech/kcapdemoserver:latest + mattintech/kcapdemoserver:${{ env.VERSION }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e440308 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,33 @@ +# Use Python 3.11 slim image as base +FROM python:3.11-slim + +# Set working directory +WORKDIR /app + +# Set environment variables +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + FLASK_APP=src/run.py + +# Install system dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc \ + && rm -rf /var/lib/apt/lists/* + +# Copy requirements first for better layer caching +COPY requirements.txt . + +# Install Python dependencies +RUN pip install --no-cache-dir -r requirements.txt + +# Copy application code +COPY . . + +# Create necessary directories for runtime +RUN mkdir -p src/app/static/images src/app/static/barcodes src/app/instance + +# Expose port 5555 +EXPOSE 5555 + +# Run the application +CMD ["python", "src/run.py"] diff --git a/README.md b/README.md index a725579..4a7dc62 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,70 @@ This project is a simple Flask API for demonstrating AR content retrieval for ba ## Setup +### Option 1: Docker Hub (Recommended) + +Pull and run the pre-built image from Docker Hub: + +```bash +# Pull the latest image +docker pull mattintech/kcapdemoserver:latest + +# Run the container +docker run -p 5555:5000 \ + -e SECRET_KEY=your-secret-key-here \ + -e DATABASE_URL=sqlite:///data/kcap_demo.db \ + -v $(pwd)/data:/app/data \ + mattintech/kcapdemoserver:latest +``` + +Or use a specific version: + +```bash +docker pull mattintech/kcapdemoserver:v1.0.0 +docker run -p 5555:5000 --env-file .env mattintech/kcapdemoserver:v1.0.0 +``` + +### Option 2: Docker Compose + +1. **Clone the Repository:** + +```bash +git clone https://github.com/mattintech/KCAPDemoServer.git +cd KCAPDemoServer +``` + +2. **Configure Environment:** + +Copy `.env.example` to `.env` and update with your Azure AD credentials: + +```bash +cp .env.example .env +``` + +Edit `.env` and set your Azure AD configuration values. + +3. **Run with Docker Compose:** + +```bash +docker-compose up -d +``` + +The application will be available at `http://localhost:5555` + +4. **View Logs:** + +```bash +docker-compose logs -f +``` + +5. **Stop the Application:** + +```bash +docker-compose down +``` + +### Option 3: Local Python Setup + 1. **Clone the Repository:** ```bash @@ -49,23 +113,26 @@ cd pip install -r requirements.txt ``` -3. **Run the Server:** +3. **Configure Environment:** + +Copy `.env.example` to `.env` and update with your configuration. + +4. **Run the Server:** ```bash -python app.py +python src/run.py ``` -The application will automatically create the necessary directories and initialize the products.json file if it doesn't exist. +The application will automatically create the necessary directories and initialize the database if it doesn't exist. -4. **Access the Admin Interface:** +### Accessing the Application -Open your browser and navigate to: +**Admin Interface:** ``` http://localhost:5555/admin ``` -5. **Test the Endpoints:** - +**API Endpoints:** * Login: `GET http://localhost:5555/login` * Content Fields: `GET http://localhost:5555/arcontentfields` * AR Info (Example): `GET http://localhost:5555/arinfo?barcode=123456` @@ -105,6 +172,18 @@ The following barcode types are available: └── generate_barcode.html # Barcode generation page ``` +## Docker Hub + +Pre-built Docker images are automatically published to Docker Hub on each release: + +**Repository**: [mattintech/kcapdemoserver](https://hub.docker.com/r/mattintech/kcapdemoserver) + +**Available Tags**: +- `latest` - Most recent release +- `v1.0.0`, `v1.0.1`, etc. - Specific version releases + +For maintainers: See [DOCKER_HUB_SETUP.md](DOCKER_HUB_SETUP.md) for information on configuring automated builds. + ## Implementation Notes * The application is designed as a single server hosting both the API endpoints and admin interface. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..189a88d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3.8' + +services: + web: + build: . + container_name: kcap-demo-server + ports: + - "5555:5555" + environment: + - FLASK_DEBUG=1 + env_file: + - .env + volumes: + # Mount static directories for persistent storage + - ./src/app/static/images:/app/src/app/static/images + - ./src/app/static/barcodes:/app/src/app/static/barcodes + # Mount instance directory for database persistence + - ./src/app/instance:/app/src/app/instance + restart: unless-stopped