Skip to content

Packaging a Gaia App

This page covers everything you need to go from working code to a deployable Cohesity Marketplace bundle: building Docker images, creating the app package, validating the AppSpec, and uploading to the DevPortal.


Prerequisites

  • Docker installed and running locally
  • appspec.yaml and app.json written for your app
  • appspecvalidator_exec binary (available from the Cohesity DevPortal)

Step 1: Write Your Dockerfile

Marketplace apps are standard Docker containers. Use the base image and build approach that fits your app — no Cohesity-specific base image is required.

Docker
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY server.py wrapper.sh ./
RUN chmod +x wrapper.sh

EXPOSE 8002

CMD ["./wrapper.sh"]
Docker
# Stage 1: Build the React frontend
FROM node:20-slim AS frontend-builder

WORKDIR /frontend
COPY frontend/package*.json ./
RUN npm ci

COPY frontend/ ./
RUN npm run build

# Stage 2: Python backend + compiled React
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY main.py settings.py api/ ./
COPY --from=frontend-builder /frontend/dist ./static

COPY wrapper.sh ./
RUN chmod +x wrapper.sh

EXPOSE 8080

CMD ["./wrapper.sh"]

The wrapper.sh Crash-Recovery Loop

Include a wrapper.sh in every image to restart the server automatically on crash:

Bash
#!/bin/bash
set -e

while true; do
    echo "[$(date -u '+%Y-%m-%dT%H:%M:%SZ')] Starting server..."
    uvicorn main:app --host 0.0.0.0 --port 8080 --workers 1

    exit_code=$?
    if [ $exit_code -eq 0 ]; then
        echo "[$(date -u '+%Y-%m-%dT%H:%M:%SZ')] Server exited cleanly."
        break
    fi

    echo "[$(date -u '+%Y-%m-%dT%H:%M:%SZ')] Crashed (exit $exit_code). Restarting in 5s..."
    sleep 5
done

The outer Kubernetes pod restart policy provides the second layer of crash recovery.


Step 2: Build the Docker Image

Bash
# Build for the target architecture
docker build -t my-gaia-app:latest .

# Verify the image starts correctly
docker run --rm -p 8080:8080 \
  -e GAIA_API_KEY="your-api-key" \
  my-gaia-app:latest

Open http://localhost:8080 and confirm the app works before packaging.

Multi-Platform Builds

If your development machine uses Apple Silicon (ARM) but the cluster runs x86-64, build for the correct platform:

Bash
docker buildx build --platform linux/amd64 -t my-gaia-app:latest .

Step 3: Write appspec.yaml and app.json

See AppSpec Reference for the complete field reference.

Minimal app.json for a Gaia app:

JSON
{
  "name": "My Gaia App",
  "description": "Chat with your knowledge bases using Cohesity Gaia",
  "version": "1.0.0",
  "min_software_version": "7.2",
  "unrestricted_app_ui_access": false
}

Set min_software_version to "7.2" for all Gaia applications — Gaia is only available on Cohesity 7.2+.


Step 4: Validate the AppSpec

Download appspecvalidator_exec from the DevPortal (or request it from your Cohesity contact), then run:

Bash
./appspecvalidator_exec appspec.yaml

Common validation errors:

Error Fix
unsupported kind: Deployment Change kind: Deployment to kind: ReplicaSet
replicas must be fixed or share Replace replicas: 1 with replicas: {fixed: 1}
cohesityTag must be 'ui' or 'cleanup' Check the tag value in your ports block
image not found in bundle Ensure image name matches between appspec and Docker save

Step 5: Create the App Bundle

The Marketplace expects a tar archive containing: 1. appspec.yaml 2. app.json 3. The Docker image saved as a .tar file

Bash
# Save the Docker image
docker save my-gaia-app:latest -o my-gaia-app.tar

# Create the bundle
tar -czf my-gaia-app-bundle.tar.gz \
  appspec.yaml \
  app.json \
  my-gaia-app.tar

Bundle size

Docker images can be large. Use python:3.11-slim (not the full python:3.11 image) and avoid installing development tools to keep the image under 500 MB.

Minimizing Image Size

Docker
# Use slim base images
FROM python:3.11-slim    # ~120MB vs ~900MB for full python:3.11

# Combine RUN commands to reduce layers
RUN pip install --no-cache-dir -r requirements.txt \
    && rm -rf /root/.cache

# Use .dockerignore to exclude unnecessary files

Example .dockerignore:

Text Only
.git
.env
__pycache__
*.pyc
node_modules
frontend/src
frontend/public
*.md
tests/

Step 6: Upload to DevPortal

  1. Log in to the Cohesity cluster UI.
  2. Navigate to AppsUpload.
  3. Select your my-gaia-app-bundle.tar.gz file.
  4. The platform validates and installs the app.
  5. Once installed, users can launch it from the Apps dashboard.

Updating an Existing App

To update a deployed app:

  1. Bump the version in app.json (e.g., "1.0.0""1.1.0").
  2. Rebuild the Docker image with the same tag.
  3. Re-create the bundle.
  4. Upload to DevPortal — it will detect the new version and perform a rolling update.

Directory Structure for a Packaged App

Text Only
my-gaia-app/
├── appspec.yaml          # Cohesity deployment manifest
├── app.json              # App metadata
├── Dockerfile            # Image build instructions
├── wrapper.sh            # Crash-recovery restart loop
├── main.py               # Application entrypoint
├── requirements.txt      # Python dependencies
├── .env.example          # Template for local development
└── frontend/             # React source (multi-stage builds only)

Next Steps