The Trinity Beast Infrastructure — Docker Setup Guide

Multi-Stage Builds, Troubleshooting Toolkit, and Container Deployment

Date: May 2026 Region: us-east-2 (Ohio) Container Images: 4 Base Image: Alpine 3.19 (Go) / Python 3.10-slim (Translation)

1. Overview

The Trinity Beast Infrastructure uses three Dockerfiles located in deployments/docker/, plus a Python container for the Translation Engine:

Additionally, 12 Go Lambda functions are built directly from the monorepo (cmd/autoops/ and cmd/queued-writer/) and deployed as zip files — not containerized.

Build Conventions

2. Container Architecture

Four images, three deployed as containers, one deployed as a Lambda zip. Plus 12 Go Lambda functions built from the monorepo:

Image ECR Repository Runs Fargate Specs
LPO Server trinity-beast-lpo-server All 4 ECS services (Main / Mirror / LRS / Webhook) 8 vCPU / 32 GB
Sync Job trinity-beast-sync-job Nightly EventBridge task 0.5 vCPU / 1 GB
Translation Worker tbi-translate-worker Step Function invoked ECS task (per doc-language pair) 1 vCPU / 3 GB
Receipt Lambda Not containerized Builds a bootstrap binary, deployed as a zip to Lambda N/A — Lambda provided.al2023
AutoOps Lambdas (10) Not containerized Built from cmd/autoops/*, deployed as zip to Lambda N/A — Lambda provided.al2023, 1770 MB
Queued Writer Lambda Not containerized Built from cmd/queued-writer/, deployed as zip to Lambda N/A — Lambda provided.al2023, 256 MB, VPC

3. Dockerfile: LPO Server (Main)

The primary Dockerfile at deployments/docker/Dockerfile. This single image runs all four ECS services — differentiated only by the SERVER_TYPE environment variable.

Full Dockerfile

# Multi-stage build for The Trinity Beast LPO Server
# Optimized for AWS Fargate (AMD64)

# Stage 1: Build
FROM --platform=linux/amd64 golang:1.26.1-alpine AS builder

# Install build dependencies
RUN apk add --no-cache git ca-certificates tzdata

# Set working directory
WORKDIR /build

# Copy go mod files
COPY go.mod go.sum ./

# Download dependencies
RUN go mod download

# Copy source code
COPY cmd/ ./cmd/
COPY pkg/ ./pkg/
COPY internal/ ./internal/

# Build the application
# CGO_ENABLED=0 for static binary
# -ldflags="-w -s" to reduce binary size
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
    -ldflags="-w -s" \
    -o trinity-beast-lpo-server \
    ./cmd/server

# Stage 2: Runtime
FROM --platform=linux/amd64 alpine:3.19

# Install runtime dependencies + troubleshooting toolkit
RUN apk add --no-cache \
    ca-certificates \
    tzdata \
    curl \
    postgresql16-client \
    python3 \
    jq \
    bind-tools \
    redis \
    htop \
    strace \
    tcpdump \
    busybox-extras \
    && rm -rf /var/cache/apk/*

# Create non-root user
RUN addgroup -g 1000 appuser && \
    adduser -D -u 1000 -G appuser appuser

# Set working directory
WORKDIR /app

# Copy binary from builder
COPY --from=builder /build/trinity-beast-lpo-server .

# Change ownership
RUN chown -R appuser:appuser /app

# Switch to non-root user
USER appuser

# Expose ports
# LPO: 8080 (TCP), 8081 (health), 2679 (UDP)
# LRS: 9090 (TCP), 9091 (health), 2680 (UDP)
EXPOSE 8080 8081 9090 9091 2679/udp 2680/udp

# Health check — dedicated health port (8081) isolated from production traffic
HEALTHCHECK --interval=60s --timeout=30s --start-period=30s --retries=10 \
    CMD curl -f http://localhost:8081/health || exit 1

# Run the application
ENTRYPOINT ["/app/trinity-beast-lpo-server"]

Stage Breakdown

Stage 1: Builder golang:1.26.1-alpine
  • Starts from golang:1.26.1-alpine with git, ca-certificates, and tzdata
  • Downloads Go module dependencies first (layer caching optimization)
  • Copies source code: cmd/, pkg/, internal/
  • Compiles a fully static binary with CGO_ENABLED=0 and stripped debug symbols (-ldflags="-w -s")
  • Output: /build/trinity-beast-lpo-server
Stage 2: Runtime alpine:3.19
  • Minimal Alpine 3.19 base image
  • Installs the full troubleshooting toolkit (psql, python3, jq, dig, redis-cli, htop, strace, tcpdump, curl, wget, nc, netstat, nslookup, top)
  • Creates non-root user appuser:1000
  • Copies the compiled binary from the builder stage
  • Exposes ports: 8080 (LPO TCP), 8081 (LPO health), 9090 (LRS TCP), 9091 (LRS health), 2679/udp (LPO UDP), 2680/udp (LRS UDP)
  • Health check: curl -f http://localhost:8081/health every 60 seconds (dedicated health port, isolated from production traffic)

SERVER_TYPE Environment Variable

The same image runs all four ECS services. The SERVER_TYPE env var (set in the ECS task definition) determines which mode the server runs in:

SERVER_TYPE ECS Service Behavior
APP_REPORT_SERVER trinity-beast-main-service Primary LPO + LRS server (TCP + UDP)
APP_REPORT_SERVER trinity-beast-mirror-service Mirror LPO + LRS server
APP_REPORT_SERVER trinity-beast-lrs-service LRS server (TCP + UDP on 9090/2680)
WEBHOOK_SERVER trinity-beast-webhook-service Outbound webhook price push (health on TCP 8083, no ALB)

4. Dockerfile: Sync Job

The sync job Dockerfile at deployments/docker/Dockerfile.sync. Same multi-stage pattern as the LPO server, but builds cmd/sync instead. No ports exposed, no health check — runs to completion and exits.

Full Dockerfile

# Multi-stage build for The Trinity Beast Sync Job
# Built from the monorepo root

FROM --platform=linux/amd64 golang:1.26.1-alpine AS builder

RUN apk add --no-cache git ca-certificates tzdata

WORKDIR /build

COPY go.mod go.sum ./
RUN go mod download

COPY cmd/ ./cmd/
COPY pkg/ ./pkg/
COPY internal/ ./internal/

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
    -ldflags="-w -s" \
    -o trinity-beast-sync-job \
    ./cmd/sync

FROM --platform=linux/amd64 alpine:3.19

RUN apk add --no-cache ca-certificates tzdata postgresql16-client python3 jq bind-tools redis htop strace tcpdump busybox-extras && \
    rm -rf /var/cache/apk/*

RUN addgroup -g 1000 appuser && \
    adduser -D -u 1000 -G appuser appuser

WORKDIR /app

COPY --from=builder /build/trinity-beast-sync-job .

RUN chown -R appuser:appuser /app

USER appuser

ENTRYPOINT ["/app/trinity-beast-sync-job"]

Key Differences from LPO Server

Sync Job Specifics scheduled task
  • Builds ./cmd/sync instead of ./cmd/server
  • Same troubleshooting toolkit installed (useful for ECS Exec debugging)
  • No ports exposed — not a long-running service
  • No health check — runs to completion and exits
  • Triggered nightly by EventBridge at 1 AM EST
  • Fargate specs: 0.5 vCPU / 1 GB (much smaller than the LPO server)

5. Dockerfile: Receipt Lambda

The receipt Lambda Dockerfile at deployments/docker/Dockerfile.receipt. This is a builder stage only — it produces a bootstrap binary for Lambda's provided.al2023 runtime. It is not deployed as a container.

Full Dockerfile

# Build for The Trinity Beast Receipt Lambda
# Built from the monorepo root — produces a bootstrap binary for Lambda

FROM --platform=linux/amd64 golang:1.26.1-alpine AS builder

RUN apk add --no-cache git ca-certificates tzdata

WORKDIR /build

COPY go.mod go.sum ./
RUN go mod download

COPY cmd/ ./cmd/
COPY pkg/ ./pkg/
COPY internal/ ./internal/

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
    -ldflags="-w -s" \
    -o bootstrap \
    ./cmd/receipt

How It Works

Lambda Deployment provided.al2023
  • Builder stage only — no runtime stage, no Alpine runtime image
  • Produces a bootstrap binary (the name Lambda expects for custom runtimes)
  • The binary is zipped and uploaded directly to Lambda — not pushed to ECR
  • Uses Lambda's provided.al2023 runtime (Amazon Linux 2023)

Build & Deploy Command

GOOS=linux GOARCH=amd64 go build -o bootstrap ./cmd/handler/
zip -j function.zip bootstrap
aws lambda update-function-code \
  --function-name trinity-beast-receipt \
  --zip-file fileb://function.zip \
  --region us-east-2

6. Translation Worker (Python Container)

The only Python container in the fleet. Runs as an ECS Fargate task invoked by the tbi-translation-orchestrator Step Function. Handles Bedrock-powered document translation with sentinel preprocessing, multi-layer validation, and retry logic.

Key Characteristics

Translation Worker Python 3.10
  • Base image: python:3.10-slim (NOT Alpine — needs full glibc for Bedrock SDK)
  • ECR repository: tbi-translate-worker
  • Fargate specs: 1 vCPU / 3 GB
  • No timeout ceiling — large docs (180KB API Reference) take ~16 minutes
  • NOT in VPC — calls Bedrock and LPO admin API over public internet
  • Invoked by Step Function via ecs:runTask.sync (waits for completion)
  • Command override passes --doc, --lang, --job-id per invocation

Build & Push

# Build from monorepo root
docker build --platform linux/amd64 \
  -f cmd/autoops/translate-worker/Dockerfile \
  -t tbi-translate-worker .

# Tag and push to ECR
docker tag tbi-translate-worker:latest \
  211998422884.dkr.ecr.us-east-2.amazonaws.com/tbi-translate-worker:latest

aws ecr get-login-password --region us-east-2 | \
  docker login --username AWS --password-stdin \
  211998422884.dkr.ecr.us-east-2.amazonaws.com

docker push \
  211998422884.dkr.ecr.us-east-2.amazonaws.com/tbi-translate-worker:latest

No Lambda update needed. The Step Function invokes this as an ECS Fargate task which pulls the :latest image from ECR on each run. Push the new image and the next translation job automatically uses it.

Environment Variables

VariablePurpose
ADMIN_KEYAdmin API key for LPO server (status updates, S3 writes)
LPO_BASEhttps://api.cpmp-site.org — LPO admin API base URL

7. AutoOps Lambda Builds

All AutoOps Lambdas are Go binaries built from cmd/autoops/ in the monorepo. They are NOT containerized — deployed as zip files directly to Lambda.

Build Pattern (Same for All 10)

# Build any AutoOps Lambda (replace <name>)
# Names: notify, self-heal, waf-action, honeypot-processor,
#         bedrock-analyze, bedrock-support, digest,
#         (translate-deploy, translate-finalize, translate-init — all DELETED 2026-06-27)

GOOS=linux GOARCH=amd64 go build -o bootstrap ./cmd/autoops/<name>/
zip -j <name>.zip bootstrap
aws lambda update-function-code \
  --function-name tbi-ops-<name> \
  --zip-file fileb://<name>.zip \
  --region us-east-2
rm bootstrap <name>.zip

Lambda Function Inventory

Function NameSourceMemoryTimeoutVPC
tbi-ops-notifycmd/autoops/notify/1770 MB60sNo
tbi-ops-self-healcmd/autoops/self-heal/1770 MB60sNo
tbi-ops-waf-actioncmd/autoops/waf-action/1770 MB60sNo
tbi-ops-honeypot-processorcmd/autoops/honeypot-processor/1770 MB60sNo
tbi-ops-bedrock-analyzecmd/autoops/bedrock-analyze/1770 MB60sNo
tbi-rhema-supportcmd/autoops/bedrock-support/1770 MB60sNo
tbi-ops-digestcmd/autoops/digest/1770 MB180sNo
trinity-beast-queued-writercmd/queued-writer/256 MB30sYes

Memory sizing: All AutoOps Lambdas use 1770 MB (multiple of 3 — project convention). The queued-writer uses 256 MB because it only does batch SQL inserts. The digest Lambda has a 180s timeout because it calls Bedrock for narrative generation.

8. Troubleshooting Toolkit

Every container (LPO Server and Sync Job) includes a full troubleshooting toolkit. These tools are available via ECS Exec for live debugging.

Tool Version Purpose
psql PostgreSQL 16.11 Aurora database queries and migrations
python3 3.11.14 Scripting, data parsing, ad-hoc automation
jq 1.7.1 JSON parsing and filtering
dig DiG 9.18.44 DNS resolution debugging
redis-cli 7.2.9 ElastiCache/Valkey debugging and queries
htop — Interactive process monitoring
strace — System call tracing for debugging hangs or crashes
tcpdump — Network packet capture for connectivity issues
curl — HTTP requests and API testing
wget — HTTP downloads
nc (netcat) — TCP/UDP connectivity testing
netstat — Network connection listing
nslookup — DNS lookups
top — Basic process monitoring

All tools are available via ECS Exec. Connect with:

aws ecs execute-command \
  --cluster trinity-beast-fargate-cluster \
  --task TASK_ID \
  --container CONTAINER_NAME \
  --interactive \
  --region us-east-2 \
  --command sh

9. Build Commands

All builds run from the monorepo root (trinity-beast-lpo-server/). The -f flag points to the Dockerfile in deployments/docker/.

LPO Server

docker build --platform linux/amd64 \
  -t trinity-beast-lpo-server \
  -f deployments/docker/Dockerfile .

Sync Job

docker build --platform linux/amd64 \
  -t trinity-beast-sync-job \
  -f deployments/docker/Dockerfile.sync .

Receipt Lambda (Not Docker — Direct Go Build)

GOOS=linux GOARCH=amd64 go build -o bootstrap ./cmd/handler/
zip -j function.zip bootstrap

10. Push to ECR

Authenticate

aws ecr get-login-password --region us-east-2 | \
  docker login --username AWS --password-stdin \
  211998422884.dkr.ecr.us-east-2.amazonaws.com

Tag & Push LPO Server

docker tag trinity-beast-lpo-server:latest \
  211998422884.dkr.ecr.us-east-2.amazonaws.com/trinity-beast-lpo-server:latest

docker push \
  211998422884.dkr.ecr.us-east-2.amazonaws.com/trinity-beast-lpo-server:latest

Tag & Push Sync Job

docker tag trinity-beast-sync-job:latest \
  211998422884.dkr.ecr.us-east-2.amazonaws.com/trinity-beast-sync-job:latest

docker push \
  211998422884.dkr.ecr.us-east-2.amazonaws.com/trinity-beast-sync-job:latest

Lambda (Direct Upload — Not ECR)

aws lambda update-function-code \
  --function-name trinity-beast-receipt \
  --zip-file fileb://function.zip \
  --region us-east-2

11. Deploy to ECS

Force Deploy All 4 Services

Forces ECS to pull the new image from ECR and start new tasks:

# Force deploy all 4 services (picks up new image from ECR)
for svc in trinity-beast-main-service trinity-beast-mirror-service trinity-beast-lrs-service trinity-beast-webhook-service; do
  aws ecs update-service \
    --cluster trinity-beast-fargate-cluster \
    --service $svc \
    --force-new-deployment \
    --region us-east-2
done

Monitor Rollout

# Monitor rollout status
for svc in trinity-beast-main-service trinity-beast-mirror-service trinity-beast-lrs-service trinity-beast-webhook-service; do
  aws ecs describe-services \
    --cluster trinity-beast-fargate-cluster \
    --services $svc \
    --region us-east-2 \
    --query "services[0].[serviceName,deployments[0].rolloutState]" \
    --output text
done

Rolling deployment: New tasks start, pass health checks, then old tasks drain. Zero downtime — MinimumHealthyPercent: 100, MaximumPercent: 200.

12. Health Checks

Check Type Method Target
Docker HEALTHCHECK curl -f http://localhost:8081/health Every 60s, 30s timeout, 10 retries. Dedicated health port isolated from production traffic.
ALB Health Check HTTP GET /health Port 8081 (LPO) and 9091 (LRS) — dedicated health servers
NLB Health Check TCP Port 8081 (UDP 2679 TG) and 9091 (UDP 2680 TG)

Quick Verification

# Main API
curl -s https://api.cpmp-site.org/health

# LRS
curl -s https://lrs.cpmp-site.org/health

13. ECS Exec (Container Access)

Connect to a Running Container

# Get task ID
TASK_ID=$(aws ecs list-tasks \
  --cluster trinity-beast-fargate-cluster \
  --service-name trinity-beast-main-service \
  --region us-east-2 \
  --query 'taskArns[0]' \
  --output text | awk -F/ '{print $NF}')

# Connect
aws ecs execute-command \
  --cluster trinity-beast-fargate-cluster \
  --task $TASK_ID \
  --container trinity-beast-main-container \
  --interactive \
  --region us-east-2 \
  --command sh

Common Troubleshooting Commands

Command Purpose
psql -h $DB_HOST -U $DB_USER -d $DB_NAME Connect to Aurora
redis-cli -h $CACHE_URL --tls -p 6379 Connect to ElastiCache
curl localhost:8080/health Local health check
dig trinity-beast-aurora-cluster.cluster-cvg4oeysemon.us-east-2.rds.amazonaws.com DNS resolution
htop Process monitoring
netstat -tlnp Listening ports

14. Container Conventions

Standards enforced
  • All containers run as non-root (appuser:1000)
  • All use Alpine 3.19 for minimal attack surface
  • All include the full troubleshooting toolkit (14 tools)
  • Static Go binaries — no runtime dependencies on Go
  • Same image for all 4 ECS services — differentiated by SERVER_TYPE env var (APP_REPORT_SERVER or WEBHOOK_SERVER)
Runtime Configuration env vars
  • GOGC=300 set at runtime for GC tuning (not in Dockerfile)
  • Ports: 8080 (LPO TCP), 8081 (LPO health), 9090 (LRS TCP), 9091 (LRS health), 2679 (LPO UDP), 2680 (LRS UDP)