Skip to content

Production CloudWatch Logs

Production containers write structured stdout/stderr logs through Docker's awslogs driver. The application already emits JSON through Pino, and Traefik is configured to emit JSON for both service and access logs.

Provision AWS resources

Deploy the log groups before starting the containers. Pass the EC2 instance-profile role name so the stack attaches the least-privilege writer policy to the Docker host:

aws cloudformation deploy \
  --region ap-south-1 \
  --stack-name dichit-production-cloudwatch-logs \
  --template-file infra/aws/cloudwatch-logs.yml \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameter-overrides DockerHostRoleName=ec2-cloudwatch-role RetentionInDays=30

Use the EC2 instance profile for credentials. Do not place AWS access keys in the Compose file or Docker daemon environment. If a customer-managed KMS key is required, pass KmsKeyArn; its key policy must allow CloudWatch Logs in ap-south-1 to use the key.

The stack retains log groups when the stack is removed and enforces a retention period while it exists. The Docker host receives only logs:CreateLogStream and logs:PutLogEvents for these groups. Group creation remains an infrastructure responsibility, so containers cannot create arbitrary log groups.

Deploy containers

The Compose defaults match the CloudFormation defaults. Override them only when the stack was deployed with different names:

AWS_REGION=ap-south-1
CLOUDWATCH_APP_LOG_GROUP=/dichit/production/app
CLOUDWATCH_TRAEFIK_LOG_GROUP=/dichit/production/traefik

Apply the logging configuration by recreating both containers:

docker compose -f docker-compose.prod.yml --env-file .env.prod up -d --force-recreate app traefik

Each container uses a unique stream name derived from its Compose name and container ID. Non-blocking delivery uses a 4 MB per-container buffer so a CloudWatch outage does not stall the API; Docker drops new log messages if that buffer fills.

Verify

docker inspect --format '{{.HostConfig.LogConfig.Type}} {{json .HostConfig.LogConfig.Config}}' traefik
aws logs tail /dichit/production/traefik --region ap-south-1 --since 10m
aws logs tail /dichit/production/app --region ap-south-1 --since 10m --follow

Also monitor the Docker daemon for delivery failures and alert on application error rates in CloudWatch Logs Insights. Log retention, metric filters, alarms, and subscriptions should remain AWS-managed resources rather than container startup side effects.