DevOps Deploy
Production checklist (always verify)
Docker: multi-stage Python
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
ENV PYTHONUNBUFFERED=1
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Docker Compose (local dev)
services:
app:
build: .
ports: ["8000:8000"]
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
volumes:
- .:/app
depends_on: [db, redis]
db:
image: postgres:15
environment:
POSTGRES_DB: app
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
pgdata:
SAM template (Lambda + DynamoDB)
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Timeout: 30
Runtime: python3.11
Environment:
Variables:
DYNAMODB_TABLE: !Ref AppTable
Resources:
AppFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: lambda_function.handler
MemorySize: 512
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref AppTable
AppTable:
Type: AWS::DynamoDB::Table
Properties:
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
TimeToLiveSpecification:
AttributeName: ttl
sam build
sam deploy --guided
sam deploy
sam deploy --no-confirm-changeset --no-fail-on-empty-changeset
sam logs -n AppFunction --tail
GitHub Actions: test + security + deploy
name: 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
- run: pytest tests/ -v --cov=src --cov-report=xml
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install bandit safety
- run: bandit -r src/ -ll
- run: safety check -r
[, ]
Health check endpoint (FastAPI)
import time, os
from fastapi import FastAPI
app = FastAPI()
START_TIME = time.time()
@app.get("/health")
async def health():
return {
"status": "healthy",
"uptime_seconds": time.time() - START_TIME,
"version": os.environ.get("APP_VERSION", "unknown"),
}
CloudWatch alarm (Python)
import boto3
def create_error_alarm(function_name: str, sns_topic_arn: str):
cw = boto3.client("cloudwatch")
cw.put_metric_alarm(
AlarmName=f"{function_name}-errors",
MetricName="Errors",
Namespace="AWS/Lambda",
Dimensions=[{"Name": "FunctionName", "Value": function_name}],
Period=300, EvaluationPeriods=1, Threshold=5,
ComparisonOperator="GreaterThanThreshold",
AlarmActions=[sns_topic_arn],
TreatMissingData="notBreaching",
)