Skip to main content

Docker Kubernetes

Docker & Kubernetes

Summary: Containerize your agents with Docker and deploy to Kubernetes for scalable, manageable production deployments.

Dockerfile

FROM python:3.11-slim

WORKDIR /app

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

## Copy application
COPY . .

## Create non-root user
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser

## Expose port
EXPOSE 3000

## Run with uvicorn
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "3000", "--workers", "4"]

requirements.txt

signalwire-agents>=1.0.10
uvicorn[standard]>=0.20.0

Application Entry Point

## app.py
from signalwire_agents import AgentBase


class MyAgent(AgentBase):
def __init__(self):
super().__init__(name="my-agent")
self.add_language("English", "en-US", "rime.spore")
self.prompt_add_section("Role", "You are a helpful assistant.")


agent = MyAgent()
app = agent._app

Building and Running

## Build image
docker build -t signalwire-agent .

## Run container
docker run -d \
-p 3000:3000 \
-e SWML_BASIC_AUTH_USER=myuser \
-e SWML_BASIC_AUTH_PASSWORD=mypassword \
--name agent \
signalwire-agent

## View logs
docker logs -f agent

## Stop container
docker stop agent

Docker Compose

## docker-compose.yml
version: '3.8'

services:
agent:
build: .
ports:
- "3000:3000"
environment:
- SWML_BASIC_AUTH_USER=${SWML_BASIC_AUTH_USER}
- SWML_BASIC_AUTH_PASSWORD=${SWML_BASIC_AUTH_PASSWORD}
- SWML_PROXY_URL_BASE=${SWML_PROXY_URL_BASE}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3

nginx:
image: nginx:alpine
ports:
- "443:443"
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/ssl/certs:ro
depends_on:
- agent
restart: unless-stopped

Run with:

docker-compose up -d

Kubernetes Deployment

Deployment Manifest

## deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: signalwire-agent
labels:
app: signalwire-agent
spec:
replicas: 3
selector:
matchLabels:
app: signalwire-agent
template:
metadata:
labels:
app: signalwire-agent
spec:
containers:
- name: agent
image: your-registry/signalwire-agent:latest
ports:
- containerPort: 3000
env:
- name: SWML_BASIC_AUTH_USER
valueFrom:
secretKeyRef:
name: agent-secrets
key: auth-user
- name: SWML_BASIC_AUTH_PASSWORD
valueFrom:
secretKeyRef:
name: agent-secrets
key: auth-password
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
periodSeconds: 10

Service Manifest

## service.yaml
apiVersion: v1
kind: Service
metadata:
name: signalwire-agent
spec:
selector:
app: signalwire-agent
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: ClusterIP

Ingress Manifest

## ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: signalwire-agent
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- agent.example.com
secretName: agent-tls
rules:
- host: agent.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: signalwire-agent
port:
number: 80

Secrets

## secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: agent-secrets
type: Opaque
stringData:
auth-user: your-username
auth-password: your-secure-password

Kubernetes Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│ Kubernetes Architecture │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Internet │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Ingress │ SSL termination, routing │
│ │ (nginx/traefik)│ │
│ └──────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Service │ Load balancing across pods │
│ │ (ClusterIP) │ │
│ └──────────────────┘ │
│ │ │
│ ├──────────────┬──────────────┐ │
│ ▼ ▼ ▼ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ Pod │ │ Pod │ │ Pod │ replicas: 3 │
│ │ Agent │ │ Agent │ │ Agent │ │
│ └────────┘ └────────┘ └────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Deploying to Kubernetes

## Create secrets
kubectl apply -f secrets.yaml

## Deploy application
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml

## Check status
kubectl get pods -l app=signalwire-agent
kubectl get svc signalwire-agent
kubectl get ingress signalwire-agent

## View logs
kubectl logs -f -l app=signalwire-agent

## Scale deployment
kubectl scale deployment signalwire-agent --replicas=5

Horizontal Pod Autoscaler

## hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: signalwire-agent
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: signalwire-agent
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70

Multi-Architecture Builds

## Build for multiple architectures
FROM --platform=$TARGETPLATFORM python:3.11-slim

## ... rest of Dockerfile

Build with:

docker buildx build --platform linux/amd64,linux/arm64 -t your-registry/agent:latest --push .

Container Best Practices

Security

  • Run as non-root user
  • Use minimal base images (slim, alpine)
  • Scan images for vulnerabilities
  • Don't store secrets in images

Performance

  • Use multi-stage builds to reduce image size
  • Layer dependencies efficiently
  • Set appropriate resource limits

Reliability

  • Add health checks
  • Use restart policies
  • Configure proper logging
  • Set graceful shutdown handling