From 2261f4686e9acb781f47cb8fb42e7ab8a13a6856 Mon Sep 17 00:00:00 2001 From: Niall Munro Date: Mon, 24 Nov 2025 23:40:10 +0000 Subject: [PATCH 1/2] Add Ollama models setup with Docker Compose and Dev Container configuration - Created `.devcontainer/devcontainer.json` for VS Code integration with Ollama models. - Added `docker-compose.yml` for orchestrating Ollama and model services. - Introduced `README.md` with usage instructions and examples for Ollama models. - Implemented `docker-compose.ollama.yml` for a complete Docker Compose setup. - Developed `quick-start-ollama.sh` script for automated setup of Ollama with pre-loaded models. - Added `build-ollama-volume.sh` script to build and publish Ollama model data volume to GHCR. --- .github/workflows/build-ollama-models.yml | 273 ++++++++++++ README.md | 1 + docs/OLLAMA_MODELS_VOLUME.md | 483 ++++++++++++++++++++++ examples/.devcontainer/devcontainer.json | 35 ++ examples/.devcontainer/docker-compose.yml | 36 ++ examples/README.md | 270 ++++++++++++ examples/docker-compose.ollama.yml | 92 +++++ examples/quick-start-ollama.sh | 165 ++++++++ scripts/build-ollama-volume.sh | 373 +++++++++++++++++ 9 files changed, 1728 insertions(+) create mode 100644 .github/workflows/build-ollama-models.yml create mode 100644 docs/OLLAMA_MODELS_VOLUME.md create mode 100644 examples/.devcontainer/devcontainer.json create mode 100644 examples/.devcontainer/docker-compose.yml create mode 100644 examples/README.md create mode 100644 examples/docker-compose.ollama.yml create mode 100755 examples/quick-start-ollama.sh create mode 100755 scripts/build-ollama-volume.sh diff --git a/.github/workflows/build-ollama-models.yml b/.github/workflows/build-ollama-models.yml new file mode 100644 index 0000000..a9f4c3b --- /dev/null +++ b/.github/workflows/build-ollama-models.yml @@ -0,0 +1,273 @@ +name: Build and Publish Ollama Models Volume + +on: + push: + branches: + - main + paths: + - '.github/workflows/build-ollama-models.yml' + - 'scripts/build-ollama-volume.sh' + pull_request: + branches: + - main + paths: + - '.github/workflows/build-ollama-models.yml' + - 'scripts/build-ollama-volume.sh' + workflow_dispatch: + inputs: + models: + description: 'Comma-separated list of Ollama models to include' + required: false + default: 'qwen3-coder:30b,nate/instinct,nomic-embed-text:v1.5' + type: string + tag: + description: 'Tag for the container image' + required: false + default: 'latest' + type: string + additional_tags: + description: 'Additional tags (comma-separated)' + required: false + default: '' + type: string + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository_owner }}/ollama-models + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + pull-requests: write + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Determine models and tags + id: config + run: | + # Determine which models to include + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + MODELS="${{ inputs.models }}" + TAG="${{ inputs.tag }}" + ADDITIONAL_TAGS="${{ inputs.additional_tags }}" + else + # Default models for automatic builds + MODELS="qwen3-coder:30b,nate/instinct,nomic-embed-text:v1.5" + TAG="latest" + ADDITIONAL_TAGS="" + fi + + echo "models=${MODELS}" >> $GITHUB_OUTPUT + echo "tag=${TAG}" >> $GITHUB_OUTPUT + echo "additional_tags=${ADDITIONAL_TAGS}" >> $GITHUB_OUTPUT + + # Create model hash for unique identification + MODEL_HASH=$(echo -n "${MODELS}" | sha256sum | cut -c1-8) + echo "model_hash=${MODEL_HASH}" >> $GITHUB_OUTPUT + + echo "Building with models: ${MODELS}" + echo "Primary tag: ${TAG}" + echo "Model hash: ${MODEL_HASH}" + + - name: Extract metadata for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=${{ steps.config.outputs.tag }} + type=raw,value=models-${{ steps.config.outputs.model_hash }} + type=ref,event=pr + type=sha,prefix={{branch}}-,enable={{is_default_branch}} + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' && steps.config.outputs.tag == 'latest' }} + labels: | + org.opencontainers.image.title=Ollama Models Data Volume + org.opencontainers.image.description=Pre-pulled Ollama models for use as a data volume + org.opencontainers.image.vendor=Smart Data Foundry + models=${{ steps.config.outputs.models }} + + - name: Create Dockerfile + run: | + mkdir -p /tmp/ollama-build + cat > /tmp/ollama-build/Dockerfile << 'EOF' + FROM --platform=linux/amd64 ghcr.io/smartdatafoundry/ollama:latest AS builder + + # Install models + ARG MODELS + RUN if [ -z "$MODELS" ]; then \ + echo "Error: MODELS build arg is required" && exit 1; \ + fi && \ + /bin/ollama serve & \ + OLLAMA_PID=$! && \ + sleep 5 && \ + IFS=',' read -ra MODEL_ARRAY <<< "$MODELS" && \ + for model in "${MODEL_ARRAY[@]}"; do \ + echo "Pulling model: $model" && \ + ollama pull "$model" || exit 1; \ + done && \ + kill $OLLAMA_PID && \ + wait $OLLAMA_PID || true + + # Create minimal data volume image + FROM scratch + + # Copy models from builder + COPY --from=builder /root/.ollama /root/.ollama + + # Add metadata + ARG MODELS + LABEL org.opencontainers.image.title="Ollama Models Data Volume" + LABEL org.opencontainers.image.description="Pre-pulled Ollama models for use as a data volume" + LABEL org.opencontainers.image.source="https://github.com/${{ github.repository }}" + LABEL org.opencontainers.image.vendor="Smart Data Foundry" + LABEL models="${MODELS}" + + # Volume mount point + VOLUME ["/root/.ollama"] + EOF + + - name: Build container image + id: build + uses: docker/build-push-action@v6 + with: + context: /tmp/ollama-build + file: /tmp/ollama-build/Dockerfile + build-args: | + MODELS=${{ steps.config.outputs.models }} + push: false + load: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Get first tag for scanning + id: first-tag + run: | + FIRST_TAG=$(echo '${{ steps.meta.outputs.tags }}' | head -n1) + echo "tag=$FIRST_TAG" >> $GITHUB_OUTPUT + echo "Using tag for scan: $FIRST_TAG" + + - name: Security Scan (Trivy) + id: security-scan + uses: smartdatafoundry/trivy-security-scan@v1.0.0 + with: + image-ref: ${{ steps.first-tag.outputs.tag }} + registry: ${{ env.REGISTRY }} + severity: 'CRITICAL,HIGH' + detailed-severity: 'CRITICAL,HIGH,MEDIUM,LOW' + ignore-unfixed: 'true' + exit-code: '0' + artifact-name: 'ollama-models-security-scan' + artifact-retention-days: '30' + github-token: ${{ secrets.GITHUB_TOKEN }} + post-pr-comment: 'true' + + - name: Push container image + if: github.event_name != 'pull_request' + uses: docker/build-push-action@v6 + with: + context: /tmp/ollama-build + file: /tmp/ollama-build/Dockerfile + build-args: | + MODELS=${{ steps.config.outputs.models }} + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Create release summary + if: github.event_name != 'pull_request' + run: | + cat >> $GITHUB_STEP_SUMMARY << EOF + ## 🎉 Ollama Models Volume Published + + **Registry:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}\` + + ### 📦 Included Models + \`\`\` + ${{ steps.config.outputs.models }} + \`\`\` + + ### 🏷️ Tags + \`\`\` + ${{ steps.meta.outputs.tags }} + \`\`\` + + ### 📥 Usage + + #### Pull the image + \`\`\`bash + docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.config.outputs.tag }} + \`\`\` + + #### Use as data volume + \`\`\`bash + # Create container from data volume + docker create --name ollama-models ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.config.outputs.tag }} + + # Run Ollama with models + docker run -d \\ + --name ollama \\ + --volumes-from ollama-models \\ + -p 11434:11434 \\ + ghcr.io/smartdatafoundry/ollama:latest + + # Verify models + docker exec ollama ollama list + \`\`\` + + ### 🔍 Security Scan + Security scan results available in workflow artifacts. + + --- + *Built on $(date -u +'%Y-%m-%d %H:%M:%S UTC')* + EOF + + - name: Comment PR + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const models = '${{ steps.config.outputs.models }}'; + const tag = '${{ steps.config.outputs.tag }}'; + const modelHash = '${{ steps.config.outputs.model_hash }}'; + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `## 🔍 Ollama Models Volume Build Preview + + **Models:** \`${models}\` + **Tag:** \`${tag}\` + **Model Hash:** \`${modelHash}\` + + The Ollama models volume has been built successfully for this PR. + + Once merged to main, it will be available at: + \`\`\` + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${tag} + ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:models-${modelHash} + \`\`\` + + Security scan results are available in the workflow artifacts.` + }); diff --git a/README.md b/README.md index 9d74dfc..4ce0d0b 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ For detailed manual setup instructions, see the **[SDF TRE Setup Guide](docs/SDF |-------|-----------| | SDF TRE usage | [`docs/SDF_TRE_SETUP.md`](docs/SDF_TRE_SETUP.md) | | Full container internals | [`docs/DEVCONTAINER.md`](docs/DEVCONTAINER.md) | +| Ollama models volume | [`docs/OLLAMA_MODELS_VOLUME.md`](docs/OLLAMA_MODELS_VOLUME.md) | | Setup scripts | [`scripts/`](scripts/) directory | | Reusable publish workflow | [`docs/BUILD_PUBLISH_CONTAINER.md`](docs/BUILD_PUBLISH_CONTAINER.md) | | Dev Container Specification | https://containers.dev | diff --git a/docs/OLLAMA_MODELS_VOLUME.md b/docs/OLLAMA_MODELS_VOLUME.md new file mode 100644 index 0000000..ad26639 --- /dev/null +++ b/docs/OLLAMA_MODELS_VOLUME.md @@ -0,0 +1,483 @@ +# Ollama Models Data Volume + +This guide explains how to build, publish, and use pre-built Ollama model data volumes from GitHub Container Registry. + +## Overview + +The Ollama Models Data Volume is a container image that contains pre-pulled Ollama models. This is useful for: + +- **Air-gapped environments**: Pre-load models where internet access is restricted +- **Faster startup**: Skip model download time in development containers +- **Consistency**: Ensure everyone uses the same model versions +- **Bandwidth optimization**: Download models once, reuse many times + +## Table of Contents + +1. [Building Locally](#building-locally) +2. [Using Pre-built Images](#using-pre-built-images) +3. [GitHub Actions Workflow](#github-actions-workflow) +4. [Integration Examples](#integration-examples) +5. [Available Models](#available-models) +6. [Troubleshooting](#troubleshooting) + +## Building Locally + +### Prerequisites + +- Docker or Podman installed +- Sufficient disk space for models (typically 2-10GB per model) +- GitHub personal access token (for pushing to GHCR) + +### Using the Build Script + +The `scripts/build-ollama-volume.sh` script provides a convenient way to build and publish Ollama model volumes. + +#### Basic Usage + +```bash +# Build with default models (llama3.2, codellama) +./scripts/build-ollama-volume.sh + +# Build with specific models +./scripts/build-ollama-volume.sh -m "llama3.2,mistral,codellama" + +# Build and push to registry +./scripts/build-ollama-volume.sh -m "llama3.2" -p +``` + +#### Script Options + +| Option | Description | Default | +|--------|-------------|---------| +| `-m, --models` | Comma-separated list of models | `llama3.2,codellama` | +| `-t, --tag` | Tag for the container image | `latest` | +| `-r, --registry` | Container registry | `ghcr.io/smartdatafoundry` | +| `-n, --name` | Image name | `ollama-models` | +| `-p, --push` | Push to registry after build | `false` | +| `-h, --help` | Display help message | - | + +#### Authentication + +Before pushing, authenticate with GitHub Container Registry: + +```bash +# Docker +echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin + +# Podman +echo $GITHUB_TOKEN | podman login ghcr.io -u USERNAME --password-stdin +``` + +### Manual Build + +If you prefer to build manually without the script: + +```bash +# Create Dockerfile +cat > Dockerfile.ollama << 'EOF' +FROM ghcr.io/smartdatafoundry/ollama:latest AS builder + +ARG MODELS +RUN /bin/ollama serve & \ + OLLAMA_PID=$! && \ + sleep 5 && \ + IFS=',' read -ra MODEL_ARRAY <<< "$MODELS" && \ + for model in "${MODEL_ARRAY[@]}"; do \ + ollama pull "$model"; \ + done && \ + kill $OLLAMA_PID + +FROM scratch +COPY --from=builder /root/.ollama /root/.ollama +VOLUME ["/root/.ollama"] +EOF + +# Build +docker build \ + --build-arg MODELS="llama3.2,codellama" \ + -t ghcr.io/smartdatafoundry/ollama-models:latest \ + -f Dockerfile.ollama . + +# Push +docker push ghcr.io/smartdatafoundry/ollama-models:latest +``` + +## Using Pre-built Images + +### Available Tags + +| Tag | Description | Example | +|-----|-------------|---------| +| `latest` | Latest stable build from main | `ghcr.io/smartdatafoundry/ollama-models:latest` | +| `models-` | Specific model combination | `ghcr.io/smartdatafoundry/ollama-models:models-a1b2c3d4` | +| `pr-` | Preview for pull request | `ghcr.io/smartdatafoundry/ollama-models:pr-42` | + +### Docker Usage + +```bash +# Pull the image +docker pull ghcr.io/smartdatafoundry/ollama-models:latest + +# Create a container from the data volume +docker create --name ollama-models ghcr.io/smartdatafoundry/ollama-models:latest + +# Run Ollama using the models volume +docker run -d \ + --name ollama \ + --volumes-from ollama-models \ + -p 11434:11434 \ + ghcr.io/smartdatafoundry/ollama:latest + +# Verify models are available +docker exec ollama ollama list +``` + +### Podman Usage + +```bash +# Pull the image +podman pull ghcr.io/smartdatafoundry/ollama-models:latest + +# Create a container from the data volume +podman create --name ollama-models ghcr.io/smartdatafoundry/ollama-models:latest + +# Run Ollama using the models volume +podman run -d \ + --name ollama \ + --volumes-from ollama-models \ + -p 11434:11434 \ + ghcr.io/smartdatafoundry/ollama:latest + +# Verify models are available +podman exec ollama ollama list +``` + +### Using Named Volumes + +For more flexibility, you can extract models to a named volume: + +```bash +# Create a named volume +docker volume create ollama-models + +# Extract models from the data volume image +docker run --rm \ + -v ollama-models:/dest \ + ghcr.io/smartdatafoundry/ollama-models:latest \ + sh -c "cp -r /root/.ollama/* /dest/" + +# Run Ollama with the named volume +docker run -d \ + --name ollama \ + -v ollama-models:/root/.ollama \ + -p 11434:11434 \ + ghcr.io/smartdatafoundry/ollama:latest +``` + +## GitHub Actions Workflow + +### Automated Builds + +The repository includes a GitHub Actions workflow that automatically builds and publishes Ollama model volumes. + +**Workflow file:** `.github/workflows/build-ollama-models.yml` + +### Triggers + +- **Push to main**: Builds with default models +- **Pull requests**: Builds for preview (no push) +- **Manual dispatch**: Build with custom models and tags + +### Manual Workflow Dispatch + +1. Go to **Actions** → **Build and Publish Ollama Models Volume** +2. Click **Run workflow** +3. Configure: + - **Models**: Comma-separated list (e.g., `llama3.2,mistral,codellama`) + - **Tag**: Primary tag (e.g., `latest`, `dev`, `v1.0`) + - **Additional tags**: Optional extra tags +4. Click **Run workflow** + +### Workflow Inputs + +| Input | Description | Default | +|-------|-------------|---------| +| `models` | Comma-separated model list | `qwen3-coder:30b,nate/instinct,nomic-embed-text:v1.5` | +| `tag` | Primary image tag | `latest` | +| `additional_tags` | Extra tags (comma-separated) | `` | + +## Integration Examples + +### Dev Container Integration + +Add to `.devcontainer/docker-compose.yml`: + +```yaml +version: '3.8' + +services: + ollama-models: + image: ghcr.io/smartdatafoundry/ollama-models:latest + volumes: + - ollama-data:/root/.ollama + + ollama: + image: ghcr.io/smartdatafoundry/ollama:latest + volumes: + - ollama-data:/root/.ollama + ports: + - "11434:11434" + + devcontainer: + image: ghcr.io/smartdatafoundry/devcontainer:latest + volumes: + - ..:/workspace:cached + working_dir: /workspace + depends_on: + - ollama + environment: + - OLLAMA_HOST=http://ollama:11434 + +volumes: + ollama-data: +``` + +And `.devcontainer/devcontainer.json`: + +```json +{ + "name": "Development with Ollama", + "dockerComposeFile": "docker-compose.yml", + "service": "devcontainer", + "workspaceFolder": "/workspace", + "forwardPorts": [11434], + "postStartCommand": "curl -s http://ollama:11434/api/tags | jq" +} +``` + +### SDF TRE Usage + +```bash +# Pull the models volume +ces-pull a a ghcr.io/smartdatafoundry/ollama-models:latest + +# Create models container +podman create --name ollama-models ghcr.io/smartdatafoundry/ollama-models:latest + +# Start Ollama with models +podman run -d \ + --name ollama \ + --restart unless-stopped \ + --volumes-from ollama-models \ + -p 11434:11434 \ + -e http_proxy \ + -e https_proxy \ + -e no_proxy \ + ghcr.io/smartdatafoundry/ollama:latest + +# Verify +podman exec ollama ollama list +``` + +### Kubernetes/OpenShift + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: ollama-with-models +spec: + initContainers: + - name: load-models + image: ghcr.io/smartdatafoundry/ollama-models:latest + volumeMounts: + - name: models + mountPath: /root/.ollama + command: ["sh", "-c", "cp -r /root/.ollama/* /dest/"] + + containers: + - name: ollama + image: ghcr.io/smartdatafoundry/ollama:latest + ports: + - containerPort: 11434 + volumeMounts: + - name: models + mountPath: /root/.ollama + + volumes: + - name: models + emptyDir: {} +``` + +## Available Models + +### Default Models + +The default build includes: + +- **llama3.2**: Meta's Llama 3.2 (general purpose) +- **codellama**: Code-specialized variant of Llama +- **mistral**: Mistral 7B (efficient general purpose) + +### Custom Model Lists + +Build with any combination of models available in the [Ollama library](https://ollama.com/library): + +```bash +# Specialized for coding +./scripts/build-ollama-volume.sh -m "codellama,deepseek-coder,starcoder2" -t "coding" + +# Lightweight models +./scripts/build-ollama-volume.sh -m "phi,gemma:2b,qwen:1.8b" -t "lightweight" + +# Large context models +./scripts/build-ollama-volume.sh -m "llama3.2:90b,mixtral:8x7b" -t "large" +``` + +### Model Size Considerations + +| Model | Approximate Size | Use Case | +|-------|-----------------|----------| +| `phi` | ~1.6 GB | Testing, resource-constrained | +| `llama3.2` | ~4.7 GB | General purpose | +| `codellama` | ~3.8 GB | Code generation | +| `mistral` | ~4.1 GB | Efficient general purpose | +| `llama3.2:70b` | ~40 GB | High performance | + +## Troubleshooting + +### Build Issues + +#### "Error: MODELS build arg is required" + +Ensure you're passing the `MODELS` build argument: + +```bash +./scripts/build-ollama-volume.sh -m "llama3.2" +``` + +#### Out of disk space + +Models can be large. Check available space: + +```bash +df -h + +# Clean up unused Docker/Podman resources +docker system prune -a +podman system prune -a +``` + +#### Model pull timeout + +Some models are large and may timeout. Increase timeout or use smaller models: + +```bash +# Build with smaller models +./scripts/build-ollama-volume.sh -m "phi,gemma:2b" +``` + +### Runtime Issues + +#### Models not available in Ollama + +Verify the volume is properly mounted: + +```bash +# Check if container exists +docker ps -a | grep ollama-models + +# Inspect volume mounts +docker inspect ollama | grep -A 10 "Mounts" + +# Check models in volume +docker run --rm --volumes-from ollama-models alpine ls -la /root/.ollama/models +``` + +#### Permission errors + +Ensure proper ownership: + +```bash +# Run Ollama as root or matching UID +docker run -d \ + --name ollama \ + --user root \ + --volumes-from ollama-models \ + -p 11434:11434 \ + ghcr.io/smartdatafoundry/ollama:latest +``` + +### Registry Issues + +#### Authentication failed + +Re-authenticate: + +```bash +# Logout +docker logout ghcr.io + +# Login with fresh token +echo $GITHUB_TOKEN | docker login ghcr.io -u YOUR_USERNAME --password-stdin +``` + +#### Rate limits + +GitHub Container Registry has rate limits. Use authenticated pulls: + +```bash +docker login ghcr.io +docker pull ghcr.io/smartdatafoundry/ollama-models:latest +``` + +## Best Practices + +1. **Tag strategy**: Use specific tags for reproducibility + ```bash + # Good - pinned version + ghcr.io/smartdatafoundry/ollama-models:models-a1b2c3d4 + + # Caution - may change + ghcr.io/smartdatafoundry/ollama-models:latest + ``` + +2. **Build for your use case**: Create specialized volumes + ```bash + # Development + ./scripts/build-ollama-volume.sh -m "codellama,phi" -t "dev" + + # Production + ./scripts/build-ollama-volume.sh -m "llama3.2:70b" -t "prod" + ``` + +3. **Verify after build**: Always test models are accessible + ```bash + docker exec ollama ollama list + docker exec ollama ollama run llama3.2 "Hello, world!" + ``` + +4. **Monitor size**: Keep track of image sizes + ```bash + docker images ghcr.io/smartdatafoundry/ollama-models + ``` + +## Resources + +- [Ollama Documentation](https://github.com/ollama/ollama) +- [Ollama Model Library](https://ollama.com/library) +- [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry) +- [Dev Containers Specification](https://containers.dev) + +## Contributing + +To add or modify models in the default build: + +1. Edit `.github/workflows/build-ollama-models.yml` +2. Update the default `MODELS` value +3. Submit a pull request +4. Wait for automated build and tests + +## License + +MIT License - See [LICENSE](../LICENSE) for details. diff --git a/examples/.devcontainer/devcontainer.json b/examples/.devcontainer/devcontainer.json new file mode 100644 index 0000000..d82c69d --- /dev/null +++ b/examples/.devcontainer/devcontainer.json @@ -0,0 +1,35 @@ +{ + "name": "Development with Ollama Models", + "dockerComposeFile": "docker-compose.yml", + "service": "devcontainer", + "workspaceFolder": "/workspace", + + "forwardPorts": [11434], + "portsAttributes": { + "11434": { + "label": "Ollama API", + "onAutoForward": "notify" + } + }, + + "customizations": { + "vscode": { + "extensions": [ + "continue.continue" + ], + "settings": { + "continue.enableTabAutocomplete": true + } + } + }, + + "postStartCommand": { + "verify-ollama": "curl -s http://ollama:11434/api/tags | jq -r '.models[].name' | sort" + }, + + "features": {}, + + "remoteEnv": { + "OLLAMA_HOST": "http://ollama:11434" + } +} diff --git a/examples/.devcontainer/docker-compose.yml b/examples/.devcontainer/docker-compose.yml new file mode 100644 index 0000000..42869fd --- /dev/null +++ b/examples/.devcontainer/docker-compose.yml @@ -0,0 +1,36 @@ +version: '3.8' + +services: + # Pre-loaded Ollama models + ollama-models: + image: ghcr.io/smartdatafoundry/ollama-models:latest + volumes: + - ollama-data:/root/.ollama + + # Ollama service + ollama: + image: ghcr.io/smartdatafoundry/ollama:latest + volumes: + - ollama-data:/root/.ollama + ports: + - "11434:11434" + environment: + - OLLAMA_ORIGINS=* + restart: unless-stopped + depends_on: + - ollama-models + + # Development container + devcontainer: + image: ghcr.io/smartdatafoundry/devcontainer:latest + volumes: + - ../..:/workspace:cached + working_dir: /workspace + environment: + - OLLAMA_HOST=http://ollama:11434 + depends_on: + - ollama + command: sleep infinity + +volumes: + ollama-data: diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..e295ca1 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,270 @@ +# Ollama Models Volume Examples + +This directory contains examples for using the Ollama models data volume in different scenarios. + +## Quick Start + +The fastest way to get started with Ollama and pre-loaded models: + +```bash +# Run the quick start script +./quick-start-ollama.sh +``` + +This script will: +1. Pull the models data volume image +2. Create a models container +3. Pull and start Ollama with the pre-loaded models +4. Verify everything is working +5. Provide usage instructions + +## Examples + +### 1. Quick Start Script + +**File:** `quick-start-ollama.sh` + +Automated setup script that configures Ollama with pre-loaded models. + +```bash +./quick-start-ollama.sh +``` + +Works with both Docker and Podman, automatically detects which is available. + +### 2. Docker Compose + +**File:** `docker-compose.ollama.yml` + +Complete Docker Compose setup with Ollama, models, and development container. + +```bash +# Start all services +docker-compose -f docker-compose.ollama.yml up -d + +# List available models +docker-compose -f docker-compose.ollama.yml exec ollama ollama list + +# Access development container +docker-compose -f docker-compose.ollama.yml exec devcontainer bash + +# Stop all services +docker-compose -f docker-compose.ollama.yml down +``` + +### 3. Dev Container Configuration + +**Directory:** `.devcontainer/` + +Complete Dev Container configuration for VS Code with Ollama integration. + +To use: +1. Copy `.devcontainer/` to your project root +2. Open project in VS Code +3. Select "Reopen in Container" +4. Models will be automatically available + +The configuration includes: +- Ollama service with pre-loaded models +- Development container with Ollama access +- Continue extension for AI-assisted coding +- Port forwarding for Ollama API + +## Usage Patterns + +### Pattern 1: Data Volume Container + +Use the models image as a data volume: + +```bash +# Create models container +docker create --name ollama-models ghcr.io/smartdatafoundry/ollama-models:latest + +# Run Ollama with models +docker run -d \ + --name ollama \ + --volumes-from ollama-models \ + -p 11434:11434 \ + ghcr.io/smartdatafoundry/ollama:latest +``` + +### Pattern 2: Named Volume + +Extract models to a named volume: + +```bash +# Create volume +docker volume create ollama-models + +# Extract models +docker run --rm \ + -v ollama-models:/dest \ + ghcr.io/smartdatafoundry/ollama-models:latest \ + sh -c "cp -r /root/.ollama/* /dest/" + +# Use volume +docker run -d \ + --name ollama \ + -v ollama-models:/root/.ollama \ + -p 11434:11434 \ + ghcr.io/smartdatafoundry/ollama:latest +``` + +### Pattern 3: Docker Compose + +Use the provided `docker-compose.ollama.yml` for multi-container setup. + +### Pattern 4: Dev Container + +Use the `.devcontainer/` configuration for VS Code integration. + +## Testing Models + +After setup, test that models are available: + +```bash +# List models +curl http://localhost:11434/api/tags + +# Run a model +curl http://localhost:11434/api/generate -d '{ + "model": "llama3.2", + "prompt": "Hello, world!", + "stream": false +}' + +# Interactive chat +docker exec -it ollama ollama run llama3.2 +``` + +## Environment-Specific Examples + +### Local Development + +Use the quick start script or Docker Compose: + +```bash +./quick-start-ollama.sh +``` + +### SDF TRE + +In restricted environments with `ces-pull`: + +```bash +# Pull models volume +ces-pull a a ghcr.io/smartdatafoundry/ollama-models:latest + +# Create and start +podman create --name ollama-models ghcr.io/smartdatafoundry/ollama-models:latest +podman run -d \ + --name ollama \ + --restart unless-stopped \ + --volumes-from ollama-models \ + -p 11434:11434 \ + -e http_proxy \ + -e https_proxy \ + -e no_proxy \ + ghcr.io/smartdatafoundry/ollama:latest +``` + +### Kubernetes/OpenShift + +See the Kubernetes example in the main documentation: [docs/OLLAMA_MODELS_VOLUME.md](../docs/OLLAMA_MODELS_VOLUME.md#kubernetesopenshift) + +## Customization + +### Using Different Models + +Build a custom models volume with specific models: + +```bash +# From repository root +./scripts/build-ollama-volume.sh -m "codellama,mistral,phi" -t "custom" +``` + +### Combining with Your Dev Container + +Integrate Ollama into your existing dev container: + +1. Add Ollama service to your `docker-compose.yml`: + ```yaml + ollama: + image: ghcr.io/smartdatafoundry/ollama:latest + volumes: + - ollama-data:/root/.ollama + ports: + - "11434:11434" + ``` + +2. Add models initialization: + ```yaml + ollama-models: + image: ghcr.io/smartdatafoundry/ollama-models:latest + volumes: + - ollama-data:/root/.ollama + ``` + +3. Update your dev container environment: + ```json + { + "remoteEnv": { + "OLLAMA_HOST": "http://ollama:11434" + } + } + ``` + +## Troubleshooting + +### Models not appearing + +```bash +# Check models container exists +docker ps -a | grep ollama-models + +# Verify volume has data +docker run --rm --volumes-from ollama-models alpine ls -la /root/.ollama/models + +# Check Ollama logs +docker logs ollama +``` + +### Connection refused + +```bash +# Ensure Ollama is running +docker ps | grep ollama + +# Test connectivity +curl http://localhost:11434/api/tags + +# Check port forwarding +docker port ollama +``` + +### Permission errors + +```bash +# Run with appropriate user +docker run -d \ + --name ollama \ + --user $(id -u):$(id -g) \ + --volumes-from ollama-models \ + -p 11434:11434 \ + ghcr.io/smartdatafoundry/ollama:latest +``` + +## Resources + +- [Main Ollama Documentation](../docs/OLLAMA_MODELS_VOLUME.md) +- [Ollama GitHub](https://github.com/ollama/ollama) +- [Ollama Model Library](https://ollama.com/library) +- [Dev Containers](https://containers.dev) + +## Contributing + +Have a useful example? Please submit a pull request! + +## License + +MIT License - See [LICENSE](../LICENSE) diff --git a/examples/docker-compose.ollama.yml b/examples/docker-compose.ollama.yml new file mode 100644 index 0000000..1982068 --- /dev/null +++ b/examples/docker-compose.ollama.yml @@ -0,0 +1,92 @@ +version: '3.8' + +# Example Docker Compose configuration for using Ollama with pre-loaded models +# in a development container setup. +# +# Usage: +# docker-compose up -d +# docker-compose exec devcontainer bash + +services: + # Data volume container with pre-pulled Ollama models + ollama-models: + image: ghcr.io/smartdatafoundry/ollama-models:latest + volumes: + - ollama-data:/root/.ollama + # This container just provides the data volume + command: ["sh", "-c", "echo 'Models loaded' && exit 0"] + + # Ollama service with models from the data volume + ollama: + image: ghcr.io/smartdatafoundry/ollama:latest + container_name: ollama + volumes: + - ollama-data:/root/.ollama + ports: + - "11434:11434" + environment: + # Optional: Configure Ollama environment variables + - OLLAMA_ORIGINS=* + # - OLLAMA_DEBUG=1 + restart: unless-stopped + depends_on: + ollama-models: + condition: service_completed_successfully + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # Development container with access to Ollama + devcontainer: + image: ghcr.io/smartdatafoundry/devcontainer:latest + container_name: devcontainer + volumes: + # Mount your workspace + - ${WORKSPACE_DIR:-.}:/workspace:cached + # Optional: Mount safe_data if in SDF TRE + # - /safe_data:/safe_data:ro + working_dir: /workspace + environment: + # Configure Ollama client to use the ollama service + - OLLAMA_HOST=http://ollama:11434 + # Proxy settings (useful in restricted environments) + - http_proxy=${http_proxy:-} + - https_proxy=${https_proxy:-} + - no_proxy=${no_proxy:-} + depends_on: + ollama: + condition: service_healthy + # Keep container running + command: ["sleep", "infinity"] + restart: unless-stopped + +volumes: + # Named volume for Ollama models + # This persists the models between container restarts + ollama-data: + +# Example usage after starting: +# +# 1. Start all services: +# docker-compose up -d +# +# 2. Check Ollama is running and models are available: +# docker-compose exec ollama ollama list +# +# 3. Test a model: +# docker-compose exec ollama ollama run llama3.2 "Hello, world!" +# +# 4. Access the development container: +# docker-compose exec devcontainer bash +# +# 5. Use Ollama from devcontainer: +# docker-compose exec devcontainer curl http://ollama:11434/api/tags +# +# 6. Stop all services: +# docker-compose down +# +# 7. Remove volumes (deletes models): +# docker-compose down -v diff --git a/examples/quick-start-ollama.sh b/examples/quick-start-ollama.sh new file mode 100755 index 0000000..6b1ad6c --- /dev/null +++ b/examples/quick-start-ollama.sh @@ -0,0 +1,165 @@ +#!/bin/bash +# +# quick-start-ollama.sh - Quick start script for Ollama with pre-loaded models +# +# This script sets up Ollama with pre-pulled models using the data volume approach. +# It's designed to work in both local Docker/Podman environments and SDF TRE. +# + +set -e + +# Colors for output +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +# Configuration +MODELS_IMAGE="ghcr.io/smartdatafoundry/ollama-models:latest" +OLLAMA_IMAGE="ghcr.io/smartdatafoundry/ollama:latest" +MODELS_CONTAINER="ollama-models" +OLLAMA_CONTAINER="ollama" +OLLAMA_PORT="11434" + +# Detect container runtime +if command -v docker &> /dev/null; then + RUNTIME="docker" +elif command -v podman &> /dev/null; then + RUNTIME="podman" +else + echo -e "${RED}Error: Neither docker nor podman found${NC}" + echo "Please install Docker or Podman first" + exit 1 +fi + +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE}Ollama Quick Start${NC}" +echo -e "${BLUE}========================================${NC}" +echo -e "${GREEN}Container runtime:${NC} ${RUNTIME}" +echo -e "${BLUE}========================================${NC}\n" + +# Function to check if a container exists +container_exists() { + ${RUNTIME} ps -a --format '{{.Names}}' | grep -q "^${1}$" +} + +# Function to check if a container is running +container_running() { + ${RUNTIME} ps --format '{{.Names}}' | grep -q "^${1}$" +} + +# Step 1: Pull the models image +echo -e "${YELLOW}Step 1: Pulling Ollama models image...${NC}" +if ${RUNTIME} pull "${MODELS_IMAGE}"; then + echo -e "${GREEN}✓ Models image pulled successfully${NC}\n" +else + echo -e "${RED}✗ Failed to pull models image${NC}" + echo "If you're in a restricted environment, you may need to use ces-pull or similar" + exit 1 +fi + +# Step 2: Create models container if it doesn't exist +echo -e "${YELLOW}Step 2: Setting up models container...${NC}" +if container_exists "${MODELS_CONTAINER}"; then + echo -e "${YELLOW}Models container already exists${NC}" +else + if ${RUNTIME} create --name "${MODELS_CONTAINER}" "${MODELS_IMAGE}"; then + echo -e "${GREEN}✓ Models container created${NC}" + else + echo -e "${RED}✗ Failed to create models container${NC}" + exit 1 + fi +fi +echo "" + +# Step 3: Pull Ollama image +echo -e "${YELLOW}Step 3: Pulling Ollama image...${NC}" +if ${RUNTIME} pull "${OLLAMA_IMAGE}"; then + echo -e "${GREEN}✓ Ollama image pulled successfully${NC}\n" +else + echo -e "${RED}✗ Failed to pull Ollama image${NC}" + exit 1 +fi + +# Step 4: Start Ollama with models +echo -e "${YELLOW}Step 4: Starting Ollama service...${NC}" + +# Stop and remove existing Ollama container if it exists +if container_exists "${OLLAMA_CONTAINER}"; then + echo -e "${YELLOW}Stopping existing Ollama container...${NC}" + ${RUNTIME} stop "${OLLAMA_CONTAINER}" 2>/dev/null || true + ${RUNTIME} rm "${OLLAMA_CONTAINER}" 2>/dev/null || true +fi + +# Start new Ollama container +if ${RUNTIME} run -d \ + --name "${OLLAMA_CONTAINER}" \ + --restart unless-stopped \ + --volumes-from "${MODELS_CONTAINER}" \ + -p "${OLLAMA_PORT}:${OLLAMA_PORT}" \ + -e http_proxy \ + -e https_proxy \ + -e no_proxy \ + "${OLLAMA_IMAGE}"; then + echo -e "${GREEN}✓ Ollama service started${NC}\n" +else + echo -e "${RED}✗ Failed to start Ollama service${NC}" + exit 1 +fi + +# Step 5: Wait for Ollama to be ready +echo -e "${YELLOW}Step 5: Waiting for Ollama to be ready...${NC}" +RETRY_COUNT=0 +MAX_RETRIES=30 +while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do + if ${RUNTIME} exec "${OLLAMA_CONTAINER}" curl -s http://localhost:11434/api/tags > /dev/null 2>&1; then + echo -e "${GREEN}✓ Ollama is ready${NC}\n" + break + fi + RETRY_COUNT=$((RETRY_COUNT + 1)) + echo -n "." + sleep 1 +done + +if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then + echo -e "\n${RED}✗ Timeout waiting for Ollama to start${NC}" + echo "Check logs: ${RUNTIME} logs ${OLLAMA_CONTAINER}" + exit 1 +fi + +# Step 6: Verify models +echo -e "${YELLOW}Step 6: Verifying available models...${NC}" +echo -e "${BLUE}Available models:${NC}" +${RUNTIME} exec "${OLLAMA_CONTAINER}" ollama list +echo "" + +# Step 7: Test a model +echo -e "${YELLOW}Step 7: Testing model...${NC}" +TEST_RESPONSE=$(${RUNTIME} exec "${OLLAMA_CONTAINER}" ollama run llama3.2 "Say 'Hello, Ollama is working!'" 2>/dev/null || echo "Test failed") +echo -e "${BLUE}Test response:${NC}" +echo "${TEST_RESPONSE}" +echo "" + +# Success summary +echo -e "${BLUE}========================================${NC}" +echo -e "${GREEN}✓ Ollama setup complete!${NC}" +echo -e "${BLUE}========================================${NC}" +echo "" +echo -e "${GREEN}Access Information:${NC}" +echo -e " API URL: ${BLUE}http://localhost:${OLLAMA_PORT}${NC}" +echo -e " Container: ${BLUE}${OLLAMA_CONTAINER}${NC}" +echo "" +echo -e "${GREEN}Useful Commands:${NC}" +echo -e " List models: ${BLUE}${RUNTIME} exec ${OLLAMA_CONTAINER} ollama list${NC}" +echo -e " Run a model: ${BLUE}${RUNTIME} exec ${OLLAMA_CONTAINER} ollama run llama3.2${NC}" +echo -e " Check status: ${BLUE}${RUNTIME} ps | grep ${OLLAMA_CONTAINER}${NC}" +echo -e " View logs: ${BLUE}${RUNTIME} logs ${OLLAMA_CONTAINER}${NC}" +echo -e " Stop Ollama: ${BLUE}${RUNTIME} stop ${OLLAMA_CONTAINER}${NC}" +echo -e " Start Ollama: ${BLUE}${RUNTIME} start ${OLLAMA_CONTAINER}${NC}" +echo -e " Remove everything: ${BLUE}${RUNTIME} rm -f ${OLLAMA_CONTAINER} ${MODELS_CONTAINER}${NC}" +echo "" +echo -e "${GREEN}Test with curl:${NC}" +echo -e " ${BLUE}curl http://localhost:${OLLAMA_PORT}/api/tags${NC}" +echo "" +echo -e "${BLUE}========================================${NC}\n" diff --git a/scripts/build-ollama-volume.sh b/scripts/build-ollama-volume.sh new file mode 100755 index 0000000..c700cda --- /dev/null +++ b/scripts/build-ollama-volume.sh @@ -0,0 +1,373 @@ +#!/bin/bash +# +# build-ollama-volume.sh - Build and publish Ollama model data volume to GHCR +# +# This script creates a container image containing pre-pulled Ollama models, +# which can be used as a data volume to speed up model loading in environments +# where direct model pulling is restricted or slow. +# +# Usage: +# ./build-ollama-volume.sh [OPTIONS] +# +# Options: +# -m, --models MODEL[,MODEL...] Comma-separated list of Ollama models to include +# (e.g., "qwen3-coder:30b,nate/instinct,nomic-embed-text:v1.5") +# -t, --tag TAG Tag for the container image (default: latest) +# -r, --registry REGISTRY Container registry (default: ghcr.io/smartdatafoundry) +# -n, --name NAME Image name (default: ollama-models) +# -p, --push Push image to registry after build +# -h, --help Display this help message +# +# Examples: +# # Build with default models +# ./build-ollama-volume.sh +# +# # Build with specific models and push +# ./build-ollama-volume.sh -m "llama3.2,codellama" -p +# +# # Build with custom tag +# ./build-ollama-volume.sh -m "mistral" -t "mistral-only" -p +# + +set -e + +# Colors for output +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Default configuration +DEFAULT_MODELS="llama3.2,codellama" +REGISTRY="ghcr.io/smartdatafoundry" +IMAGE_NAME="ollama-models" +TAG="latest" +PUSH_IMAGE=false +MODELS="" + +# Function to display usage +usage() { + cat << EOF +Usage: $0 [OPTIONS] + +Build and publish Ollama model data volume to GHCR + +Options: + -m, --models MODEL[,MODEL...] Comma-separated list of Ollama models to include + (default: ${DEFAULT_MODELS}) + -t, --tag TAG Tag for the container image (default: ${TAG}) + -r, --registry REGISTRY Container registry (default: ${REGISTRY}) + -n, --name NAME Image name (default: ${IMAGE_NAME}) + -p, --push Push image to registry after build + -h, --help Display this help message + +Examples: + # Build with default models + $0 + + # Build with specific models and push + $0 -m "llama3.2,codellama" -p + + # Build with custom tag + $0 -m "mistral" -t "mistral-only" -p + +EOF +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -m|--models) + MODELS="$2" + shift 2 + ;; + -t|--tag) + TAG="$2" + shift 2 + ;; + -r|--registry) + REGISTRY="$2" + shift 2 + ;; + -n|--name) + IMAGE_NAME="$2" + shift 2 + ;; + -p|--push) + PUSH_IMAGE=true + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo -e "${RED}Error: Unknown option $1${NC}" + usage + exit 1 + ;; + esac +done + +# Use default models if none specified +if [ -z "$MODELS" ]; then + MODELS="$DEFAULT_MODELS" +fi + +# Full image reference +FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}" + +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE}Ollama Model Volume Builder${NC}" +echo -e "${BLUE}========================================${NC}" +echo -e "${GREEN}Registry:${NC} ${REGISTRY}" +echo -e "${GREEN}Image:${NC} ${IMAGE_NAME}" +echo -e "${GREEN}Tag:${NC} ${TAG}" +echo -e "${GREEN}Models:${NC} ${MODELS}" +echo -e "${GREEN}Push:${NC} ${PUSH_IMAGE}" +echo -e "${BLUE}========================================${NC}\n" + +# Create temporary directory for build context +BUILD_DIR=$(mktemp -d) +trap "rm -rf ${BUILD_DIR}" EXIT + +echo -e "${YELLOW}Creating build context in ${BUILD_DIR}${NC}\n" + +# Create Dockerfile +cat > "${BUILD_DIR}/Dockerfile" << 'EOF' +FROM --platform=linux/amd64 ghcr.io/smartdatafoundry/ollama:latest AS builder + +# Install models +ARG MODELS +RUN if [ -z "$MODELS" ]; then \ + echo "Error: MODELS build arg is required" && exit 1; \ + fi && \ + # Start Ollama service in background + /bin/ollama serve & \ + OLLAMA_PID=$! && \ + sleep 5 && \ + # Pull each model + echo "$MODELS" | tr ',' '\n' | while read -r model; do \ + if [ -n "$model" ]; then \ + echo "Pulling model: $model" && \ + ollama pull "$model" || exit 1; \ + fi; \ + done && \ + # Stop Ollama service + kill $OLLAMA_PID && \ + wait $OLLAMA_PID || true + +# Create minimal data volume image +FROM scratch + +# Copy models from builder +COPY --from=builder /root/.ollama /root/.ollama + +# Add metadata +LABEL org.opencontainers.image.title="Ollama Models Data Volume" +LABEL org.opencontainers.image.description="Pre-pulled Ollama models for use as a data volume" +LABEL org.opencontainers.image.source="https://github.com/smartdatafoundry/devcontainer" +LABEL org.opencontainers.image.vendor="Smart Data Foundry" +LABEL models="${MODELS}" + +# Volume mount point +VOLUME ["/root/.ollama"] + +# Default command (won't actually run in scratch, but documents usage) +CMD ["Models available in /root/.ollama"] +EOF + +# Create README for the image +cat > "${BUILD_DIR}/README.md" << EOF +# Ollama Models Data Volume + +This container image contains pre-pulled Ollama models and is designed to be used as a data volume. + +## Included Models + +\`\`\` +${MODELS} +\`\`\` + +## Usage + +### Using with Docker/Podman + +Mount this image as a volume to an Ollama container: + +\`\`\`bash +# Create a container from the data volume image +docker create --name ollama-models ${FULL_IMAGE} + +# Run Ollama with the models volume +docker run -d \\ + --name ollama \\ + --volumes-from ollama-models \\ + -p 11434:11434 \\ + ghcr.io/smartdatafoundry/ollama:latest +\`\`\` + +### Using with Podman + +\`\`\`bash +# Create a container from the data volume image +podman create --name ollama-models ${FULL_IMAGE} + +# Run Ollama with the models volume +podman run -d \\ + --name ollama \\ + --volumes-from ollama-models \\ + -p 11434:11434 \\ + ghcr.io/smartdatafoundry/ollama:latest +\`\`\` + +### Using in Dev Containers + +Add to your \`.devcontainer/devcontainer.json\`: + +\`\`\`json +{ + "name": "Development with Ollama", + "dockerComposeFile": "docker-compose.yml", + "service": "devcontainer", + "workspaceFolder": "/workspace" +} +\`\`\` + +And in \`.devcontainer/docker-compose.yml\`: + +\`\`\`yaml +version: '3.8' + +services: + ollama-models: + image: ${FULL_IMAGE} + volumes: + - ollama-data:/root/.ollama + + ollama: + image: ghcr.io/smartdatafoundry/ollama:latest + volumes: + - ollama-data:/root/.ollama + ports: + - "11434:11434" + + devcontainer: + image: ghcr.io/smartdatafoundry/devcontainer:latest + volumes: + - ..:/workspace + depends_on: + - ollama + environment: + - OLLAMA_HOST=http://ollama:11434 + +volumes: + ollama-data: +\`\`\` + +## Verifying Models + +After mounting the volume, verify models are available: + +\`\`\`bash +docker exec ollama ollama list +\`\`\` + +## Building + +This image was built using: + +\`\`\`bash +./scripts/build-ollama-volume.sh -m "${MODELS}" -t "${TAG}" +\`\`\` + +## Registry + +Published to: ${FULL_IMAGE} + +EOF + +# Build the container +echo -e "${YELLOW}Building container image...${NC}\n" + +if command -v docker &> /dev/null; then + CONTAINER_CMD="docker" +elif command -v podman &> /dev/null; then + CONTAINER_CMD="podman" +else + echo -e "${RED}Error: Neither docker nor podman found${NC}" + exit 1 +fi + +echo -e "${BLUE}Using container runtime: ${CONTAINER_CMD}${NC}\n" + +# Build with BuildKit/Buildah +${CONTAINER_CMD} build \ + --build-arg "MODELS=${MODELS}" \ + --tag "${FULL_IMAGE}" \ + --label "build.date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \ + --label "build.models=${MODELS}" \ + --label "build.tag=${TAG}" \ + "${BUILD_DIR}" + +echo -e "\n${GREEN}✓ Build complete!${NC}\n" + +# Show image info +echo -e "${BLUE}Image Information:${NC}" +${CONTAINER_CMD} images "${FULL_IMAGE}" +echo "" + +# Push if requested +if [ "$PUSH_IMAGE" = true ]; then + echo -e "${YELLOW}Pushing image to registry...${NC}\n" + + # Check if logged in (basic check) + if ${CONTAINER_CMD} login ghcr.io --get-login &> /dev/null || \ + grep -q "ghcr.io" "${HOME}/.docker/config.json" 2>/dev/null || \ + grep -q "ghcr.io" "${XDG_RUNTIME_DIR}/containers/auth.json" 2>/dev/null; then + ${CONTAINER_CMD} push "${FULL_IMAGE}" + echo -e "\n${GREEN}✓ Image pushed successfully!${NC}\n" + + # Create additional tags + echo -e "${BLUE}Creating additional tags...${NC}\n" + + # Tag with model list hash for unique identification + MODEL_HASH=$(echo -n "${MODELS}" | sha256sum | cut -c1-8) + MODEL_TAG="${REGISTRY}/${IMAGE_NAME}:models-${MODEL_HASH}" + ${CONTAINER_CMD} tag "${FULL_IMAGE}" "${MODEL_TAG}" + ${CONTAINER_CMD} push "${MODEL_TAG}" + echo -e "${GREEN}✓ Also tagged as: ${MODEL_TAG}${NC}\n" + + else + echo -e "${RED}Error: Not logged in to ${REGISTRY}${NC}" + echo -e "${YELLOW}Please login first:${NC}" + echo -e " ${CONTAINER_CMD} login ghcr.io" + exit 1 + fi +else + echo -e "${YELLOW}Image built but not pushed (use -p to push)${NC}\n" +fi + +# Print usage instructions +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE}Usage Instructions${NC}" +echo -e "${BLUE}========================================${NC}" +echo -e "\n${GREEN}Test locally:${NC}" +echo -e " ${CONTAINER_CMD} create --name ollama-models ${FULL_IMAGE}" +echo -e " ${CONTAINER_CMD} run -d --name ollama --volumes-from ollama-models -p 11434:11434 ghcr.io/smartdatafoundry/ollama:latest" +echo -e " ${CONTAINER_CMD} exec ollama ollama list" + +if [ "$PUSH_IMAGE" = true ]; then + echo -e "\n${GREEN}Pull from registry:${NC}" + echo -e " ${CONTAINER_CMD} pull ${FULL_IMAGE}" +fi + +echo -e "\n${GREEN}Available models in this volume:${NC}" +IFS=',' read -ra MODEL_ARRAY <<< "$MODELS" +for model in "${MODEL_ARRAY[@]}"; do + echo -e " • ${model}" +done + +echo -e "\n${BLUE}========================================${NC}\n" +echo -e "${GREEN}✓ Done!${NC}\n" From 146abba78a6b94d51a025787b1af083f94894293 Mon Sep 17 00:00:00 2001 From: Niall Munro Date: Mon, 24 Nov 2025 23:44:23 +0000 Subject: [PATCH 2/2] chore: comment out push and pull request triggers in build workflow and update documentation --- .github/workflows/build-ollama-models.yml | 24 +++++++++++------------ docs/OLLAMA_MODELS_VOLUME.md | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build-ollama-models.yml b/.github/workflows/build-ollama-models.yml index a9f4c3b..25c73ea 100644 --- a/.github/workflows/build-ollama-models.yml +++ b/.github/workflows/build-ollama-models.yml @@ -1,18 +1,18 @@ name: Build and Publish Ollama Models Volume on: - push: - branches: - - main - paths: - - '.github/workflows/build-ollama-models.yml' - - 'scripts/build-ollama-volume.sh' - pull_request: - branches: - - main - paths: - - '.github/workflows/build-ollama-models.yml' - - 'scripts/build-ollama-volume.sh' + # push: + # branches: + # - main + # paths: + # - '.github/workflows/build-ollama-models.yml' + # - 'scripts/build-ollama-volume.sh' + # pull_request: + # branches: + # - main + # paths: + # - '.github/workflows/build-ollama-models.yml' + # - 'scripts/build-ollama-volume.sh' workflow_dispatch: inputs: models: diff --git a/docs/OLLAMA_MODELS_VOLUME.md b/docs/OLLAMA_MODELS_VOLUME.md index ad26639..0d8a46a 100644 --- a/docs/OLLAMA_MODELS_VOLUME.md +++ b/docs/OLLAMA_MODELS_VOLUME.md @@ -184,8 +184,8 @@ The repository includes a GitHub Actions workflow that automatically builds and ### Triggers -- **Push to main**: Builds with default models -- **Pull requests**: Builds for preview (no push) +- ~~**Push to main**: Builds with default models~~ +- ~~**Pull requests**: Builds for preview (no push)~~ - **Manual dispatch**: Build with custom models and tags ### Manual Workflow Dispatch