Guide to Using “Shell” Deployments in GRACE

Guide to Using “Shell” Deployments in GRACE
stand: 2024-06-10
Overview

The Shell Deployments feature in GRACE allows you to run any service you define via a shell script, exposed on port 8000. You have full control over the environment, dependencies, and service logic. The base environment is Ubuntu + Python.

  • Image Building – Create a snapshot of your application environment.
  • Deployment – Launch the snapshot as a running service.

Phase 1: Image Building
  1. (Optional) Define grace.apt
    If your service requires system-level packages, list them in a file named grace.apt. These will be installed via the apt package manager during image build.
    Example grace.apt:
    curl
    libssl-dev
    
  2. Provide Image Metadata
    When prompted, enter:
    • Name – A unique identifier for your image.
    • Version – Useful for tracking changes.
    • Description – Brief summary of what the image does.
  3. Define grace.sh
    This shell script is the entry point for your service. It should:
    • Set up the environment.
    • Start your service on port 8000.
    Example grace.sh:
    uv sync
    uv run fastapi run app.py --port 8000
    
  4. Build the Image (Snapshot)
    From your project directory, initiate the image build process. This will package your code, dependencies, and any specified system packages into a deployable snapshot.

Phase 2: Deployment
  1. Deploy the Built Image
    Select the image you built in Phase 1.
  2. Configure Deployment Settings
    Provide:
    • Name – Deployment name.
    • Resources – CPU, memory, etc.
    • Scaling Strategy – Optional; define how the service scales.
  3. Click Deploy
    Your service will start and be accessible on port 8000.
    If the deployment fails, inspect the logs to troubleshoot.

Example Project

Below is an example of a simple FastAPI service and the required configuration files for a shell deployment in GRACE:

app.py
from fastapi import FastAPI, HTTPException
import numpy as np
import pandas as pd
from pydantic import BaseModel
app = FastAPI()
class InputData(BaseModel):
    MedInc: float
    HouseAge: float
    AveRooms: float
    AveBedrms: float
    Population: float | int
    AveOccup: float
    Latitude: float
    Longitude: float
class EmptyData(BaseModel):
    Empty: str
@app.post("/predict")
async def predict(data: InputData | list[InputData]):
    try:
        if isinstance(data, InputData):
            data = [data]
        df = pd.DataFrame([p.model_dump() for p in data])
        y_pred = np.random.rand(len(df)).tolist()
        return {"predictions": y_pred}
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"Error: {e}")
@app.post("/test")
async def test(data: EmptyData | list[EmptyData]):
    try:
        return {"test answer": "hello world"}
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"Error: {e}")
pyproject.toml
[project]
name = "shell-api"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
    "fastapi[standard]>=0.116.1",
    "pandas>=2.3.1",
    "pydantic>=2.10.6",
    "scikit-learn>=1.7.1",
]
grace.sh
uv sync
uv run fastapi run app.py --port 8000

Notes
  • The service must listen on port 8000.
  • Logs are available for debugging if deployment fails.
  • You can install additional Python packages via pyproject.toml and system packages via grace.apt.