This guide covers deploying Fred using Docker for production-ready containerization.
Docker provides several benefits for deploying Fred:
We'll create three Docker-related files:
This simple Dockerfile gets Fred running quickly:
Dockerfile
🔗 ↑ TOC# Use official Python runtime as base image
FROM python:3.9-slim
# Set working directory in container
WORKDIR /app
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements first for better caching
COPY requirements.txt .
# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Copy Fred application
COPY fred.py .
# Create non-root user for security
RUN useradd -m -u 1000 freduser && chown -R freduser:freduser /app
# Switch to non-root user
USER freduser
# Expose the port Fred runs on
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD python -c "import requests; requests.get('http://localhost:3000/health', auth=('${SWML_BASIC_AUTH_USER}', '${SWML_BASIC_AUTH_PASSWORD}'))"
# Run Fred
CMD ["python", "fred.py"]
For smaller, more secure images, use a multi-stage build:
Dockerfile.multi
🔗 ↑ TOC# Stage 1: Build environment
FROM python:3.9-slim as builder
# Set working directory
WORKDIR /app
# Install build dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
python3-dev \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements
COPY requirements.txt .
# Install Python dependencies to a specific directory
RUN pip install --no-cache-dir --target=/app/deps -r requirements.txt
# Stage 2: Runtime environment
FROM python:3.9-slim
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PYTHONPATH=/app/deps:$PYTHONPATH
# Set working directory
WORKDIR /app
# Copy dependencies from builder
COPY --from=builder /app/deps /app/deps
# Copy application
COPY fred.py .
# Create non-root user
RUN useradd -m -u 1000 freduser && chown -R freduser:freduser /app
# Switch to non-root user
USER freduser
# Expose port
EXPOSE 3000
# Health check endpoint
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:3000/health').read()"
# Run Fred
CMD ["python", "fred.py"]
For easier management and configuration:
docker-compose.yml
🔗 ↑ TOCversion: '3.8'
services:
fred:
# Build from local Dockerfile
build:
context: .
dockerfile: Dockerfile
# Container name
container_name: fred-bot
# Restart policy
restart: unless-stopped
# Port mapping
ports:
- "3000:3000"
# Environment variables
environment:
# Authentication
- SWML_BASIC_AUTH_USER=${FRED_AUTH_USER:-fred_user}
- SWML_BASIC_AUTH_PASSWORD=${FRED_AUTH_PASSWORD:-secure_password_123}
# SignalWire configuration
- SWML_PROXY_URL_BASE=${PROXY_URL:-}
# Python settings
- PYTHONUNBUFFERED=1
# Timezone
- TZ=America/New_York
# Health check
healthcheck:
test: ["CMD", "python", "-c", "import requests; requests.get('http://localhost:3000/health', auth=('${SWML_BASIC_AUTH_USER:-fred_user}', '${SWML_BASIC_AUTH_PASSWORD:-secure_password_123}'))"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# Logging configuration
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# Resource limits
deploy:
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
.env
(Environment Configuration) 🔗 ↑ TOC# Authentication
FRED_AUTH_USER=fred_prod
FRED_AUTH_PASSWORD=your_secure_password_here
# Proxy configuration (if needed)
# PROXY_URL=https://your-domain.com
# Other settings
TZ=America/New_York
# Build the image
docker build -t fred-bot:latest .
# Run with environment variables
docker run -d \
--name fred \
-p 3000:3000 \
-e SWML_BASIC_AUTH_USER=fred_user \
-e SWML_BASIC_AUTH_PASSWORD=secure_password \
fred-bot:latest
# View logs
docker logs -f fred
# Stop Fred
docker stop fred
# Remove container
docker rm fred
# Start Fred (builds if needed)
docker-compose up -d
# View logs
docker-compose logs -f
# Stop Fred
docker-compose down
# Rebuild and restart
docker-compose up -d --build
# Scale to multiple instances
docker-compose up -d --scale fred=3
Create a more secure Dockerfile:
# Use distroless base image for minimal attack surface
FROM python:3.9-slim as builder
# ... build steps ...
FROM gcr.io/distroless/python3-debian11
COPY --from=builder /app /app
WORKDIR /app
EXPOSE 3000
ENTRYPOINT ["python", "fred.py"]
Never hardcode credentials. Use Docker secrets or environment files:
# docker-compose with secrets
version: '3.8'
secrets:
fred_password:
file: ./secrets/fred_password.txt
services:
fred:
# ... other config ...
secrets:
- fred_password
environment:
- SWML_BASIC_AUTH_PASSWORD_FILE=/run/secrets/fred_password
Add nginx for SSL termination:
# docker-compose with nginx
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./certs:/etc/nginx/certs
depends_on:
- fred
fred:
# Remove external port exposure
expose:
- "3000"
# ... rest of config ...
Add Prometheus metrics and centralized logging:
# Enhanced docker-compose
version: '3.8'
services:
fred:
# ... fred config ...
labels:
- "prometheus.io/scrape=true"
- "prometheus.io/port=3000"
- "prometheus.io/path=/metrics"
promtail:
image: grafana/promtail:latest
volumes:
- /var/log:/var/log
- ./promtail-config.yml:/etc/promtail/config.yml
command: -config.file=/etc/promtail/config.yml
Use Watchtower for automatic updates:
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 300 fred-bot
Push to a registry for cloud deployment:
# Tag for registry
docker tag fred-bot:latest myregistry.com/fred-bot:latest
# Push to registry
docker push myregistry.com/fred-bot:latest
# Deploy from registry
docker run -d \
--name fred \
-p 3000:3000 \
--env-file .env \
myregistry.com/fred-bot:latest
For Kubernetes, create a deployment manifest:
apiVersion: apps/v1
kind: Deployment
metadata:
name: fred-bot
spec:
replicas: 3
selector:
matchLabels:
app: fred-bot
template:
metadata:
labels:
app: fred-bot
spec:
containers:
- name: fred
image: myregistry.com/fred-bot:latest
ports:
- containerPort: 3000
env:
- name: SWML_BASIC_AUTH_USER
valueFrom:
secretKeyRef:
name: fred-secrets
key: username
- name: SWML_BASIC_AUTH_PASSWORD
valueFrom:
secretKeyRef:
name: fred-secrets
key: password
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "1000m"
# List containers
docker ps -a
# Inspect container
docker inspect fred
# Check resource usage
docker stats fred
# Execute shell in running container
docker exec -it fred /bin/bash
# Run one-off command
docker exec fred python -c "import signalwire_agents; print(signalwire_agents.__version__)"
Docker deployment provides a robust, scalable way to run Fred in production. Start with the basic Dockerfile for development, then move to multi-stage builds and orchestration for production deployments.