Claude Code × AWS ECS/Fargate Komplettanleitung | Sichere Container-Deployments
ECS/Fargate mit Claude Code bereitstellen: Docker, ECR, Task Definitions, Logs, IAM und Praxisfallen.
ECS/Fargate ist eine solide Wahl, wenn Container auf AWS laufen sollen, ohne EC2-Instanzen selbst zu verwalten. Schwierig ist aber nicht Docker selbst. Schwierig ist das Zusammenspiel aus ECR, Task Definitions, IAM-Rollen, Secrets Manager, Load Balancing, CloudWatch Logs, Health Checks und Kostenkontrolle.
In diesem Leitfaden ist Claude Code ein Implementierungsassistent, kein ungeprüfter Autopilot. Eine Task Definition ist die Startbeschreibung des Containers, Fargate ist die serverlose Laufzeitumgebung, die ihn ausführt, die execution role erlaubt ECS Image Pull, Secrets und Logs, und die task role nutzt der Anwendungscode für AWS API-Aufrufe.
Bei einer echten Migration von Masa scheiterte der erste Versuch nicht an Docker, sondern am Health Check. Die App brauchte etwa 40 Sekunden zum Starten, ECS prüfte aber zu früh. Claude Code kann die Dateien schnell schreiben, braucht aber klare Betriebsregeln: Startzeit, privates Netzwerk, Logs, Rollback und welche IAM-Berechtigung zu welcher Rolle gehört.
Zielarchitektur
Developer
|
| docker build / push
v
Amazon ECR ----> Amazon ECS Service on AWS Fargate
|
| pulls secrets / writes logs
v
Secrets Manager CloudWatch Logs
^
|
Application Load Balancer -> /health -> Node.js container
Die Beispiele verwenden ap-northeast-1, eine bestehende VPC und eine bestehende ALB target group. Wenn Netzwerk und ALB ebenfalls mit IaC entstehen sollen, passt der interne Claude Code × AWS CloudFormation/CDK Guide dazu. Für Berechtigungen lohnt sich vorher der Claude Code × AWS IAM Guide.
Drei praktische Einsatzfälle
| Einsatzfall | Warum Fargate passt | Worauf achten |
|---|---|---|
| SaaS REST API | Zwei oder mehr Tasks hinter einem ALB, Rolling Deployments ohne Serverpflege | DB-Verbindungen und Health Checks zuerst planen |
| Admin Backend | Klein starten ohne EC2-Patches oder AMIs | desiredCount 0 macht die erste Anfrage langsam |
| Gemeinsames API- und Batch-Image | Gleiches Image für Service und run-task nutzbar | Task role strikt begrenzen |
Für kurze, ereignisgesteuerte Workloads ist Claude Code × AWS Lambda oft einfacher. Fargate lohnt sich bei dauerhaftem HTTP, längeren Requests, Docker-Parität oder Runtimes, die nicht gut zu Lambda passen.
1. Minimale API mit Health Check
Beginne mit einer App, die lokal funktioniert. /health wird von ECS und ALB gelesen und sollte leichtgewichtig bleiben. Wenn eine kurzfristig langsame Datenbank sofort 500 auslöst, kann ECS gesunde Tasks ersetzen.
{
"scripts": {
"start": "node src/server.js"
},
"dependencies": {
"express": "^4.19.2"
}
}
// src/server.js
const express = require("express");
const app = express();
const port = Number(process.env.PORT || 3000);
app.get("/health", (_req, res) => {
res.status(200).json({
ok: true,
service: "myapp",
time: new Date().toISOString(),
});
});
app.get("/", (_req, res) => {
res.json({ message: "Hello from ECS Fargate" });
});
app.listen(port, "0.0.0.0", () => {
console.log(`myapp listening on ${port}`);
});
# Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY src ./src
ENV NODE_ENV=production
ENV PORT=3000
EXPOSE 3000
CMD ["node", "src/server.js"]
Prüfe curl -f http://localhost:3000/health, bevor ECS ins Spiel kommt. Im Prompt an Claude Code sollten dieselbe Health-Route für ALB und ECS, 0.0.0.0 als Listen-Adresse und startPeriod für die Startphase stehen.
2. Build und Push nach ECR
Dieses Script erstellt das Repository bei Bedarf, meldet Docker an, baut das Image und pusht einen versionierten Tag. Nur latest zu verwenden erschwert Rollback und Audit.
set -euo pipefail
export AWS_REGION="ap-northeast-1"
export AWS_ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
export ECR_REPOSITORY="myapp"
export IMAGE_TAG="$(git rev-parse --short HEAD 2>/dev/null || date +%Y%m%d%H%M%S)"
export IMAGE_URI="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPOSITORY}:${IMAGE_TAG}"
aws ecr describe-repositories \
--repository-names "${ECR_REPOSITORY}" \
--region "${AWS_REGION}" >/dev/null 2>&1 || \
aws ecr create-repository \
--repository-name "${ECR_REPOSITORY}" \
--image-scanning-configuration scanOnPush=true \
--region "${AWS_REGION}"
aws ecr get-login-password --region "${AWS_REGION}" | \
docker login --username AWS --password-stdin \
"${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"
docker build -t "${IMAGE_URI}" .
docker push "${IMAGE_URI}"
echo "Pushed ${IMAGE_URI}"
Der offizielle ECR-Ablauf nutzt get-login-password. In CI solltest du GitHub Actions OIDC und kurzlebige AWS Credentials bevorzugen, statt langfristige Access Keys in Repository-Secrets zu speichern.
3. ECS Task Definition registrieren
Fargate Tasks nutzen awsvpc. Wenn Secrets Manager Werte injiziert, braucht die execution role secretsmanager:GetSecretValue; bei einem selbst verwalteten KMS Key zusätzlich kms:Decrypt. Die task role ist für den Anwendungscode da.
set -euo pipefail
export AWS_REGION="ap-northeast-1"
export AWS_ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
export IMAGE_URI="${IMAGE_URI:?Run the ECR push script first}"
export EXECUTION_ROLE_ARN="arn:aws:iam::${AWS_ACCOUNT_ID}:role/ecsTaskExecutionRole"
export TASK_ROLE_ARN="arn:aws:iam::${AWS_ACCOUNT_ID}:role/myapp-task-role"
export SECRET_ARN="arn:aws:secretsmanager:${AWS_REGION}:${AWS_ACCOUNT_ID}:secret:prod/myapp/DATABASE_URL"
aws logs create-log-group --log-group-name /ecs/myapp --region "${AWS_REGION}" 2>/dev/null || true
aws logs put-retention-policy --log-group-name /ecs/myapp --retention-in-days 30 --region "${AWS_REGION}"
cat > ecs-task-definition.json <<EOF
{
"family": "myapp-task",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "${EXECUTION_ROLE_ARN}",
"taskRoleArn": "${TASK_ROLE_ARN}",
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"containerDefinitions": [
{
"name": "app",
"image": "${IMAGE_URI}",
"essential": true,
"portMappings": [
{ "containerPort": 3000, "hostPort": 3000, "protocol": "tcp" }
],
"environment": [
{ "name": "NODE_ENV", "value": "production" },
{ "name": "PORT", "value": "3000" }
],
"secrets": [
{ "name": "DATABASE_URL", "valueFrom": "${SECRET_ARN}" }
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/myapp",
"awslogs-region": "${AWS_REGION}",
"awslogs-stream-prefix": "ecs"
}
},
"healthCheck": {
"command": ["CMD-SHELL", "wget -qO- http://localhost:3000/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
}
}
]
}
EOF
aws ecs register-task-definition \
--cli-input-json file://ecs-task-definition.json \
--region "${AWS_REGION}"
startPeriod verhindert, dass ECS den Container bewertet, bevor die Anwendung realistisch starten konnte.
4. Fargate Service erstellen
Der folgende Befehl nutzt bestehende private Subnets, eine Task Security Group und eine ALB Target Group. Die Task Security Group sollte Port 3000 nur von der ALB Security Group erlauben.
set -euo pipefail
export AWS_REGION="ap-northeast-1"
export CLUSTER_NAME="myapp-cluster"
export SERVICE_NAME="myapp-service"
export TASK_FAMILY="myapp-task"
export SUBNET_1="subnet-xxxxxxxx"
export SUBNET_2="subnet-yyyyyyyy"
export TASK_SECURITY_GROUP="sg-xxxxxxxx"
export TARGET_GROUP_ARN="arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/myapp/abc123"
aws ecs create-cluster \
--cluster-name "${CLUSTER_NAME}" \
--region "${AWS_REGION}" >/dev/null
aws ecs create-service \
--cluster "${CLUSTER_NAME}" \
--service-name "${SERVICE_NAME}" \
--task-definition "${TASK_FAMILY}" \
--desired-count 2 \
--launch-type FARGATE \
--platform-version LATEST \
--health-check-grace-period-seconds 90 \
--network-configuration "awsvpcConfiguration={subnets=[${SUBNET_1},${SUBNET_2}],securityGroups=[${TASK_SECURITY_GROUP}],assignPublicIp=DISABLED}" \
--load-balancers "targetGroupArn=${TARGET_GROUP_ARN},containerName=app,containerPort=3000" \
--region "${AWS_REGION}"
aws ecs wait services-stable \
--cluster "${CLUSTER_NAME}" \
--services "${SERVICE_NAME}" \
--region "${AWS_REGION}"
Bei privaten Subnets mit assignPublicIp=DISABLED braucht die Task trotzdem Zugriff auf ECR, CloudWatch Logs und Secrets Manager. Nutze NAT Gateway oder VPC Endpoints. NAT ist bequem, kann aber in kleinen Testumgebungen der größte Kostenblock sein.
5. CloudWatch Logs und ECS Events prüfen
ECS-Diagnose braucht meist Service Events, Gründe gestoppter Tasks und Anwendungslogs. Gib Claude Code alle drei, wenn es ein fehlgeschlagenes Deployment analysieren soll.
export AWS_REGION="ap-northeast-1"
export CLUSTER_NAME="myapp-cluster"
export SERVICE_NAME="myapp-service"
aws ecs describe-services \
--cluster "${CLUSTER_NAME}" \
--services "${SERVICE_NAME}" \
--query "services[0].events[0:5].[createdAt,message]" \
--output table \
--region "${AWS_REGION}"
aws ecs list-tasks \
--cluster "${CLUSTER_NAME}" \
--service-name "${SERVICE_NAME}" \
--desired-status STOPPED \
--region "${AWS_REGION}"
aws logs tail /ecs/myapp \
--follow \
--since 10m \
--region "${AWS_REGION}"
Häufige Fehler sind blockierter ECR Pull, fehlender Secret-Zugriff, ALB erreicht die Task Security Group nicht, oder die App hört nur auf localhost statt 0.0.0.0.
Implementierungs-Prompt für Claude Code
Erstelle eine AWS ECS/Fargate Deployment-Implementierung für eine Node.js API.
Kontext:
- Region: ap-northeast-1
- ECR repository: myapp
- Container port: 3000
- Health endpoint: /health
- ECS launch type: FARGATE
- Network mode: awsvpc
- Desired count: 2
- Task CPU/memory: 512 / 1024
- Secret: DATABASE_URL aus Secrets Manager injizieren
- Logs: CloudWatch Logs /ecs/myapp, retention 30 days
Lieferumfang:
1. Production Dockerfile
2. Bash Script für Push nach ECR
3. Bash Script zum Registrieren der ECS task definition
4. Bash Script zum Erstellen des Fargate service
5. Bash Script zum Prüfen von CloudWatch Logs
6. Erklärung, die execution role und task role trennt
Einschränkungen:
- Kein Pseudocode. Die Befehle müssen nach Variablenbefüllung mit AWS CLI lauffähig sein.
- Keine Secret-Werte hardcoden.
- Task nicht direkt in einer public subnet veröffentlichen.
- Am Ende offizielle AWS-Dokumentationspunkte nennen, die geprüft werden müssen.
Offizielle AWS-Prüfpunkte
- AWS Fargate Guide: Fargate-Einschränkungen und Plattformverhalten.
- Task Definition Parameters:
awsvpc, CPU/memory und Health Check. - Task execution IAM role: Berechtigungen für ECR Pull, Logs und Secrets Manager.
- ECS Logs an CloudWatch senden: Setup des
awslogsDrivers. - AWS Fargate Pricing: abhängig von Region, vCPU, Memory, zusätzlichem ephemeral storage und Laufzeit.
- AWS Regional Services: prüfen, ob die Zielregion alle Services unterstützt.
Konkrete Fallen
Die erste Falle ist die Verwechslung von execution role und task role. ECR, Logging und Secret Retrieval gehören in die execution role. DynamoDB, S3, SQS und App-Berechtigungen gehören in die task role.
Die zweite ist ein Secret in der falschen Region. ECS Task, Secrets Manager Secret und KMS Key müssen zusammenpassen. In Multi-Region-Systemen sollte die Secret ARN eine Deployment-Variable pro Umgebung sein.
Die dritte ist Kostenkontrolle. Fargate ist nutzungsbasiert, aber ALB, NAT Gateway, CloudWatch Logs und ECR Storage zählen ebenfalls. Für Tests: Log-Retention setzen, ungenutzte Services stoppen und NAT prüfen.
Die vierte ist ein zu strenger Health Check. Halte /health leicht und verschiebe tiefe Abhängigkeitschecks nach /ready oder in Smoke Tests.
Die fünfte ist Image-Architektur. Wer auf Apple Silicon ARM64 baut und die Task als X86_64 definiert, bekommt Startfehler. Nutze docker buildx build --platform linux/amd64 oder passe runtimePlatform an.
CTA und nächster Schritt
Einzelne Entwickler können diese Scripts in eine kleine API kopieren und mit dem kostenlosen Claude Code Cheatsheet bessere Prompts bauen. Teams, die ECS, IAM, CI/CD, Observability und Rollback gemeinsam gestalten müssen, starten mit Claude Code Training und Beratung. Wiederverwendbare Prompts und Review-Material gibt es bei den ClaudeCodeLab Produkten.
Zusammenfassung
ECS/Fargate ist nicht nur ein Ort für Docker Images. Es ist ein gemeinsames Designproblem aus IAM, Netzwerk, Secrets, Logs, Health Checks und Kosten. Claude Code ist am stärksten, wenn zuerst die Betriebsregeln feststehen und danach lauffähige Dateien entstehen.
Im praktischen Test kam die größte Verbesserung nicht vom Dockerfile, sondern vom Prompt. Die explizite Trennung von execution role und task role, CloudWatch-Log-Befehle und Health Check Grace Period verhinderten Wiederholungsfehler. Der erste Lauf zeigte trotzdem eine fehlende Secret-Berechtigung, aber mit ECS Events und Logs lieferte Claude Code die IAM-Korrektur und Redeploy-Schritte in einem Durchgang.
Kostenloses PDF: Claude-Code-Cheatsheet
E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.
Wir schützen Ihre Daten und senden keinen Spam.
Über den Autor
Masa
Engineer für praktische Claude-Code-Workflows und Team-Einführung.
Ähnliche Artikel
Claude Code Workflow von Obsidian zu CLAUDE.md
Obsidian-Arbeitsnotizen in CLAUDE.md-Betriebsnotizen verwandeln und Kontext nicht ständig neu erklären.
Claude Code Revenue CTA Routing: Artikel zu PDF, Gumroad und Beratung führen
Ein Claude-Code-Ablauf, der Leser nach Absicht zu Gratis-PDF, Gumroad oder Beratung führt.
Claude-Code-Team-Handoff-Regeln: Belege, Berechtigungen, Rollback und Umsatzpfade
Ein praktisches Claude-Code-Handoff für Review-Belege, Berechtigungen, Rollback, Gratis-PDF, Gumroad und Beratung.