Module 09 Intermediate 24 min read

Cloud Deployment

Deploy to Streamlit Community Cloud, Render, and AWS (EC2/ECS/Lambda) — with a GitHub Actions CI/CD pipeline and production monitoring.

Updated 2025 · Edit on GitHub

Deployment Options

Your trained model and API are ready. Now you need to make them accessible to the world. Here are the three most practical options, from simplest to most powerful:

StreamlitTurn a Python script into an interactive web app in minutes. Zero frontend code. Best for demos, dashboards, and internal tools. Free tier on Streamlit Community Cloud.
RenderDeploy Docker containers or Python services from GitHub with near-zero configuration. Free tier available. Excellent for REST APIs and full-stack apps.
AWS (EC2 / ECS / SageMaker)Production-grade, highly scalable, every possible feature. EC2 for full control. ECS/Fargate for container orchestration. SageMaker for managed ML-specific infrastructure.

Streamlit — Fastest Path to a Demo

Python
# pip install streamlit joblib scikit-learn
# File: streamlit_app.py

import streamlit as st
import joblib
import numpy as np
import pandas as pd

# ── Page config
st.set_page_config(
    page_title="Breast Cancer Predictor | ZeroToML",
    page_icon="🔬",
    layout="wide"
)

# ── Load model (cached — only loads once across sessions)
@st.cache_resource
def load_model():
    return joblib.load("models/v1/pipeline.joblib")

pipe = load_model()
feature_names = [
    "mean radius", "mean texture", "mean perimeter", "mean area",
    "mean smoothness", "mean compactness", "mean concavity",
    "mean concave points", "mean symmetry", "mean fractal dimension",
    "radius SE", "texture SE", "perimeter SE", "area SE",
    "smoothness SE", "compactness SE", "concavity SE",
    "concave points SE", "symmetry SE", "fractal dimension SE",
    "worst radius", "worst texture", "worst perimeter", "worst area",
    "worst smoothness", "worst compactness", "worst concavity",
    "worst concave points", "worst symmetry", "worst fractal dimension"
]

# ── UI
st.title("🔬 Breast Cancer Tumour Predictor")
st.caption("ZeroToML · Module 09 Demo · github.com/Muhammad-waqas1/zerotoml")
st.markdown("Enter tumour measurements and click **Predict** to classify as Malignant or Benign.")

# ── Input sliders (two columns)
st.subheader("Tumour Features")
col1, col2 = st.columns(2)
inputs = []
for i, name in enumerate(feature_names):
    col = col1 if i % 2 == 0 else col2
    val = col.slider(name.title(), 0.0, 100.0, 15.0, step=0.1, key=f"f{i}")
    inputs.append(val)

# ── Predict
if st.button("🔍 Predict", type="primary", use_container_width=True):
    X = np.array(inputs).reshape(1, -1)
    pred   = pipe.predict(X)[0]
    prob   = pipe.predict_proba(X)[0][pred]
    label  = "🟢 Benign" if pred == 1 else "🔴 Malignant"

    st.divider()
    col_res, col_prob = st.columns(2)
    col_res.metric("Prediction", label)
    col_prob.metric("Confidence", f"{prob:.1%}")

    # Probability bar chart
    prob_df = pd.DataFrame({
        "Class": ["Malignant", "Benign"],
        "Probability": pipe.predict_proba(X)[0]
    })
    st.bar_chart(prob_df.set_index("Class"))

# ── Footer
st.divider()
st.caption("⚠️ For educational purposes only. Not for clinical use.")
Bash
# Run locally
streamlit run streamlit_app.py

# ── Deploy to Streamlit Community Cloud (free):
# 1. Push your code to GitHub (github.com/Muhammad-waqas1/zerotoml)
# 2. Go to share.streamlit.io
# 3. Click "New app" → select repo → select streamlit_app.py → Deploy
# That's it. Live URL in ~2 minutes.

Render — Deploy Docker API

Bash
# ── render.yaml (Infrastructure-as-Code for Render)
# Commit this file to your repo root
Python
# render.yaml
services:
  - type: web
    name: zerotoml-api
    env: docker
    plan: free                              # free tier: 512MB RAM
    dockerfilePath: ./Dockerfile
    envVars:
      - key: ENV
        value: production
    healthCheckPath: /health
    autoDeploy: true                        # redeploy on every git push
Bash
# Deploy to Render:
# 1. Push to GitHub: github.com/Muhammad-waqas1/zerotoml
# 2. Go to render.com → New → Web Service
# 3. Connect GitHub repo → Render detects render.yaml automatically
# 4. Click "Create Web Service" → Live in ~3 minutes

# Your API will be at: https://zerotoml-api.onrender.com
curl https://zerotoml-api.onrender.com/health

AWS Deployment — Production at Scale

Bash
# ── Option A: EC2 (Virtual Machine — full control)
# Launch a t3.small Ubuntu 22.04 instance in AWS console
# SSH in and run:
sudo apt update && sudo apt install -y docker.io
sudo docker pull Muhammad-waqas1/zerotoml-api:1.0.0
sudo docker run -d -p 80:8000 --restart always Muhammad-waqas1/zerotoml-api:1.0.0

# ── Option B: ECS Fargate (serverless containers — no VM management)
# Create task definition + service via AWS Console or CLI:
aws ecs create-cluster --cluster-name zerotoml-cluster
aws ecs register-task-definition --cli-input-json file://task-def.json
aws ecs create-service   --cluster zerotoml-cluster   --service-name zerotoml-api   --task-definition zerotoml-api:1   --desired-count 2   --launch-type FARGATE   --network-configuration "awsvpcConfiguration={subnets=[subnet-xxx],securityGroups=[sg-xxx],assignPublicIp=ENABLED}"

# ── Option C: AWS Lambda (serverless, pay-per-request — best for low traffic)
# pip install mangum   # ASGI adapter for Lambda
# Add to app.py: from mangum import Mangum; handler = Mangum(app)
# Deploy with: serverless framework or AWS SAM

CI/CD Pipeline (GitHub Actions)

Automate testing + Docker build + deployment on every push to main:

Python
# .github/workflows/deploy.yml

name: Test, Build & Deploy

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: {{ python-version: "3.11" }}
      - run: pip install -r requirements.txt pytest
      - run: pytest tests/ -v

  build-and-deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{{{ secrets.DOCKER_USERNAME }}}}
          password: ${{{{ secrets.DOCKER_TOKEN }}}}

      - name: Build and Push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: Muhammad-waqas1/zerotoml-api:latest

      - name: Deploy to Render
        run: |
          curl -X POST "${{{{ secrets.RENDER_DEPLOY_HOOK_URL }}}}"

Production Monitoring

LoggingLog every prediction request: input hash, prediction, latency. Use Python logging module → CloudWatch / Datadog.
Data driftMonitor input feature distributions over time. Alert when they diverge from training distribution (use KS test). Indicates model needs retraining.
Model performanceIf ground truth labels arrive with a delay (e.g., churn prediction — you know in 30 days), track accuracy over rolling windows.
ToolsMLflow for experiment tracking. Evidently AI for drift monitoring. Prometheus + Grafana for infra metrics.

Summary

  • Streamlit: fastest path to a shareable demo. Deploy free from GitHub in 2 minutes.
  • Render: Docker container deployment from GitHub. Near-zero config. Great for REST APIs.
  • AWS ECS/Fargate: production-grade container orchestration. No server management. Auto-scaling.
  • GitHub Actions: automate test → build → push → deploy on every commit to main.
  • Monitor data drift and model performance in production — models degrade as the world changes.