This guide explains how to use Docker with the Jentic Arazzo Generator and deploy it to AWS ECS.
The project includes Docker configurations for both the API server and CLI tool modes:
docker/Dockerfile: Multi-purpose container that can run either the API server or CLI tooldocker/docker-compose.yml: Local development setup with services for both API and CLIdocker/.dockerignore: Optimizes Docker builds by excluding unnecessary filesdocker/.env: Environment variables file for storing API keys and configurationdocker/.env.example: Template for the environment variables file
The Docker configuration uses environment variables for API keys and other settings:
- We provide a template file
.env.examplethat shows the structure and expected variables - You should create your own
.envfile with your actual API keys:
cp docker/.env.example docker/.env
# Edit docker/.env with your actual API keys- The
.envfile is included in.gitignoreto prevent committing sensitive information
The .env file supports the following variables:
ANTHROPIC_API_KEY: API key for Anthropic ClaudeOPENAI_API_KEY: API key for OpenAI ChatGPTGEMINI_API_KEY: API key for Google GeminiHOST: Host address for the API server (default: 0.0.0.0)PORT: Port for the API server (default: 8000)LOG_LEVEL: Logging level (default: info)
# From the project root directory
docker build --platform linux/amd64 -t jentic-arazzo-generator -f docker/Dockerfile .# Using docker directly with .env file
docker run -p 8000:8000 \
--env-file docker/.env \
jentic-arazzo-generator
# Using docker-compose (from the project root)
docker-compose -f docker/docker-compose.yml up arazzo-api# Using docker directly with .env file
docker run --rm \
--env-file docker/.env \
-v $(pwd)/output:/app/output \
jentic-arazzo-generator python -m arazzo_generator.cli.main generate <url> --output /app/output/result.yaml
# Using docker-compose (from the project root)
docker-compose -f docker/docker-compose.yml run arazzo-cli generate <url> --output /app/output/result.yamlThese steps outline deploying the Arazzo Generator as an API service on AWS ECS using the EC2 launch type and Bridge networking mode.
- AWS CLI installed and configured (
aws configure). - Docker installed.
- An existing ECS Cluster (e.g.,
ecs-qa1) configured to use EC2 instances. - An existing Application Load Balancer (ALB) and a Target Group configured with
target-type: instance. - SSM Parameters created for API keys (e.g.,
/jentic/arazzo/gemini_api_key,/jentic/arazzo/anthropic_api_key,/jentic/arazzo/openai_api_key).
An IAM role is required for ECS tasks to pull images from ECR and read secrets from SSM.
Create trust-policy.json:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}Create the role and attach required policies:
# Replace <your-region> and <your-account-id> with your specific values
AWS_REGION=<your-region>
ROLE_NAME=ecsTaskExecutionRole
aws iam create-role --role-name ${ROLE_NAME} --assume-role-policy-document file://trust-policy.json --region ${AWS_REGION}
# Attach standard ECS Task Execution policy
aws iam attach-role-policy --role-name ${ROLE_NAME} --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy --region ${AWS_REGION}
# Attach policy for SSM Parameter Store access (adjust if using different secret storage)
aws iam attach-role-policy --role-name ${ROLE_NAME} --policy-arn arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess --region ${AWS_REGION}Note: Ensure the user/role performing the deployment has iam:PassRole permissions for this execution role.
# Replace <your-account-id>, <your-region>, and <repo-name> (e.g., jentic-arazzo-generator)
AWS_ACCOUNT_ID=<your-account-id>
AWS_REGION=<your-region>
ECR_REPO_NAME=<repo-name>
IMAGE_TAG=latest
# Build for linux/amd64 architecture
docker build --platform linux/amd64 -t ${ECR_REPO_NAME}:${IMAGE_TAG} -f docker/Dockerfile ..
# Login to ECR
aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
# Tag the image
docker tag ${ECR_REPO_NAME}:${IMAGE_TAG} ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPO_NAME}:${IMAGE_TAG}
# Push the image
docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPO_NAME}:${IMAGE_TAG}The docker/ecs-task-def.json file defines the task. Key configurations for EC2/Bridge mode:
family: A unique name (e.g.,jentic-arazzo-generator-task).networkMode: Set tobridge.executionRoleArn: The ARN of theecsTaskExecutionRolecreated in Step 1.containerDefinitions[].portMappings: DefinecontainerPort(e.g., 8000) and sethostPortto0for dynamic port allocation.containerDefinitions[].secrets: ConfigurevalueFromto point to your SSM Parameter ARNs for API keys.containerDefinitions[].logConfiguration: Defineawslogs-group(e.g.,/ecs/jentic-arazzo-generator-task),awslogs-region, andawslogs-stream-prefix.cpuandmemory: Define resource limits (these are reservations for EC2, not hard limits like Fargate).- Remove
requiresCompatibilitiesor set it to["EC2"].
Update docker/ecs-task-def.json with your specific ARNs, region, account ID, log group name, and repository URI.
The log group specified in the task definition must exist before tasks can start.
# Replace <log-group-name> (e.g., /ecs/jentic-arazzo-generator-task) and <your-region>
aws logs create-log-group --log-group-name <log-group-name> --region <your-region># Ensure you are in the docker/ directory or provide the full path
aws ecs register-task-definition --cli-input-json file://ecs-task-def.json --region <your-region>Note the taskDefinitionArn from the output (e.g., arn:aws:ecs:...:task-definition/your-family:1).
If creating a new service:
# Replace placeholders: <your-cluster>, <your-service-name>, <task-definition-arn:version>, <target-group-arn>, <container-name>, <container-port>
aws ecs create-service \
--cluster <your-cluster> \
--service-name <your-service-name> \
--task-definition <task-definition-arn:version> \
--desired-count 1 \
--launch-type EC2 \
--load-balancers targetGroupArn=<target-group-arn>,containerName=<container-name>,containerPort=<container-port> \
--region <your-region>If updating an existing service (e.g., to deploy a new image version):
# Replace placeholders: <your-cluster>, <your-service-name>, <task-definition-arn:version>
aws ecs update-service \
--cluster <your-cluster> \
--service <your-service-name> \
--task-definition <task-definition-arn:version> \
--force-new-deployment \
--region <your-region>- Check the service status in the AWS ECS console or via CLI:
aws ecs describe-services --cluster <your-cluster> --services <your-service-name> --region <your-region>
- Check the target group health in the AWS EC2 console (Load Balancing -> Target Groups) or via CLI:
aws elbv2 describe-target-health --target-group-arn <target-group-arn> --region <your-region>
- Check container logs in CloudWatch Logs.
- Access the service via the Load Balancer's DNS name.
The Docker setup supports the following environment variables:
ANTHROPIC_API_KEY: API key for Anthropic ClaudeOPENAI_API_KEY: API key for OpenAI ChatGPTGEMINI_API_KEY: API key for Google GeminiPYTHONPATH: Set to/appin the containerPYTHONUNBUFFERED: Set to1for unbuffered output
- Store API keys in AWS Secrets Manager or Parameter Store
- Use IAM roles with least privilege
- Configure security groups to restrict access to the service
- Consider using AWS WAF for additional protection
For production workloads, consider:
- Setting up auto-scaling based on CPU/memory utilization
- Using Application Load Balancer for distributing traffic
- Implementing CloudWatch alarms for monitoring
- Setting up proper logging and metrics collection