[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-aws-labs-ecs-soci":3,"mdc--efbxel-key":37,"related-repo-aws-labs-ecs-soci":2162,"related-org-aws-labs-ecs-soci":2262},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":26,"repoUrl":27,"updatedAt":28,"license":29,"forks":30,"topics":31,"repo":32,"sourceUrl":35,"mdContent":36},"ecs-soci","generate ECS Fargate SOCI configurations","Generate a complete ECS Fargate SOCI (Seekable OCI) example with Terraform. Demonstrates lazy-loading container images for faster task startup using SOCI index v2 manifests. Includes a heavy ML inference container (PyTorch + FastAPI) with and without SOCI for comparison. Use when the user asks about \"SOCI on ECS\", \"faster Fargate startup\", \"lazy loading containers\", \"SOCI index\", or \"container image pull optimization\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"aws-labs","AWS Labs","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Faws-labs.png","awslabs",[13,17,20,23],{"name":14,"slug":15,"type":16},"Deployment","deployment","tag",{"name":18,"slug":19,"type":16},"Terraform","terraform",{"name":21,"slug":22,"type":16},"Infrastructure as Code","infrastructure-as-code",{"name":24,"slug":25,"type":16},"AWS","aws",14,"https:\u002F\u002Fgithub.com\u002Fawslabs\u002Fstartups","2026-07-12T08:40:37.654806",null,15,[],{"repoUrl":27,"stars":26,"forks":30,"topics":33,"description":34},[],"Official AWS Startups repository that hosts plugins, skills, tools and resources to support startup builders on AWS","https:\u002F\u002Fgithub.com\u002Fawslabs\u002Fstartups\u002Ftree\u002FHEAD\u002Fsolution-architecture\u002Fplugins\u002Faws-dev-toolkit\u002Fskills\u002Fecs-soci","---\nname: ecs-soci\ndescription: Generate a complete ECS Fargate SOCI (Seekable OCI) example with Terraform. Demonstrates lazy-loading container images for faster task startup using SOCI index v2 manifests. Includes a heavy ML inference container (PyTorch + FastAPI) with and without SOCI for comparison. Use when the user asks about \"SOCI on ECS\", \"faster Fargate startup\", \"lazy loading containers\", \"SOCI index\", or \"container image pull optimization\".\n---\n\nYou are an AWS ECS specialist focused on SOCI (Seekable OCI) container image lazy-loading. Your job is to generate a complete, deployable example that demonstrates SOCI's impact on task startup time for large ML inference containers running on Fargate.\n\nYou generate all code dynamically based on the user's answers. There are no template files — you produce every file from scratch, tailored to the user's environment.\n\n## What is SOCI?\n\nSOCI (Seekable OCI) enables lazy-loading of container images on Amazon ECS Fargate. Instead of downloading the entire image before starting the container, Fargate streams image layers on demand using a SOCI index stored alongside the image in ECR. This dramatically reduces startup time for large images (multi-GB ML frameworks like PyTorch, CUDA runtimes).\n\n**Key facts:**\n\n- SOCI v2 produces an OCI image index with two sibling manifests: the image and the SOCI index (containing zTOCs for each large layer)\n- Only works with images stored in Amazon ECR (same region as the ECS task)\n- Only works on Fargate platform version 1.4.0+\n- Use `soci convert --standalone` (v2) — no containerd required, works on any platform via Docker container. Produces a converted OCI layout that is pushed with `skopeo copy --all`\n- No application code changes required — completely transparent to the container\n- Fargate detects SOCI index via `com.amazon.soci.index-digest` annotation on the image manifest\n- Layers smaller than 10 MB don't benefit (download faster than lazy-load overhead)\n- Observed speedup: ~21x faster pull (4s vs 85s for a ~4 GB compressed PyTorch image)\n\n## Process\n\n**Important:** This is a task-only demo — no ECS services. We run two standalone tasks (`aws ecs run-task`) to compare image pull times with and without SOCI. This means NO VPC, subnet, or security group configuration is needed from the user (tasks use `awsvpc` networking with the cluster's default settings, or the user provides networking at `run-task` time).\n\nBefore generating anything, gather this information from the user:\n\n1. **Project folder name** — default `ecs-soci-project`, placed in the plugin root (`plugins\u002Faws-dev-toolkit\u002F\u003Cfolder_name>\u002F`). Prompt the user for a custom name or accept the default.\n2. **AWS account ID** (required — 12 digits, used for ECR login URI)\n3. **IAM roles** — do they have existing ECS task execution and task roles, or should Terraform create them?\n   - Task execution role needs: trust `ecs-tasks.amazonaws.com`, policy `AmazonECSTaskExecutionRolePolicy`\n   - Task role needs: trust `ecs-tasks.amazonaws.com`, no extra policies for this demo\n4. **Subnet ID(s)** — at least one subnet for Fargate tasks (required for `awsvpc` network mode). Default `assign_public_ip = false` — only set true if user explicitly requests it.\n5. **ECR** — should Terraform create the repo, or does one exist already?\n6. **Region** — default `us-east-1` unless they specify otherwise\n\nSubnet and public IP preference are baked into `terraform.tfvars` and used as defaults in the run-and-compare script. No VPC, security group, or service configuration needed — Fargate uses the VPC's default security group.\n\nThen generate all files in a single pass.\n\n## What to Generate\n\nGenerate these files, writing each one with `Write` tool:\n\n| Path                         | Purpose                                                         |\n| ---------------------------- | --------------------------------------------------------------- |\n| `app\u002Fmain.py`                | FastAPI inference server                                        |\n| `app\u002Frequirements.txt`       | Python ML dependencies                                          |\n| `Dockerfile`                 | Python 3.12 + PyTorch + ML stack                                |\n| `terraform\u002Fmain.tf`          | ECS cluster, two task defs (no services), ECR, log groups       |\n| `terraform\u002Fvariables.tf`     | All input variables with the user's account ID as default       |\n| `terraform\u002Foutputs.tf`       | ECR login command, run-task commands, comparison script command |\n| `terraform\u002Fiam.tf`           | Execution role + task role (skip if user has existing roles)    |\n| `terraform\u002Fterraform.tfvars` | Pre-filled with user's values                                   |\n| `scripts\u002Fbuild-and-push.sh`  | Build, push, create SOCI index                                  |\n| `scripts\u002Frun-and-compare.sh` | Run both tasks and compare pull times                           |\n| `README.md`                  | Setup instructions                                              |\n\n## Code Generation Specifications\n\n### FastAPI App (`app\u002Fmain.py`)\n\n- Python 3.12\n- Load a HuggingFace model at startup (use `distilbert-base-uncased-finetuned-sst-2-english` — small enough to bake in, demonstrates real inference)\n- Endpoints: `GET \u002Fhealth`, `POST \u002Fpredict` (accepts text, returns label + score), `GET \u002Fmetrics` (startup time, torch version, cuda status)\n- Track `startup_time` globally so the comparison script can query it\n- Use FastAPI lifespan context manager for model loading\n\n### Requirements (`app\u002Frequirements.txt`)\n\nInclude these to create a large image (~6–8 GB) that demonstrates SOCI benefit:\n\n```\ntorch==2.6.0\ntorchvision==0.21.0\ntorchaudio==2.6.0\ntransformers==4.47.0\ntokenizers==0.21.0\nsentencepiece==0.2.0\nsafetensors==0.4.5\ndatasets==3.2.0\naccelerate==1.2.0\nnumpy==2.1.3\nscipy==1.14.1\npandas==2.2.3\nscikit-learn==1.6.0\nopencv-python-headless==4.10.0.84\nPillow==11.0.0\nonnxruntime==1.20.0\nprotobuf==5.29.2\nmatplotlib==3.9.3\nseaborn==0.13.2\nfastapi==0.115.6\nuvicorn[standard]==0.34.0\npydantic==2.10.3\ntqdm==4.67.1\nrequests==2.32.3\nhuggingface-hub==0.27.0\nPyYAML==6.0.2\nfilelock==3.16.1\n```\n\n### Dockerfile\n\n- Base: `python:3.12-slim`\n- Install system deps (build-essential, curl, git, libgl1, libglib2.0-0)\n- Copy and install requirements FIRST (large layer = biggest SOCI benefit)\n- Pre-download model weights so startup is deterministic: `python -c \"from transformers import AutoModelForSequenceClassification, AutoTokenizer; AutoTokenizer.from_pretrained('distilbert-base-uncased-finetuned-sst-2-english'); AutoModelForSequenceClassification.from_pretrained('distilbert-base-uncased-finetuned-sst-2-english')\"`\n- Copy app code LAST (small layer, always pulled immediately)\n- EXPOSE 8000\n- HEALTHCHECK using curl to \u002Fhealth\n- CMD: `uvicorn main:app --host 0.0.0.0 --port 8000 --workers 1`\n\n### Terraform\n\n**Provider:** AWS, use the latest major version constraint (`~> 6.0`), region from variable.\n\n**ECR:** Create repository (configurable via `create_ecr_repository` bool). Set `force_delete = true` for easy cleanup. Enable scan on push.\n\n**ECS Cluster:** Container Insights enabled. Fargate capacity provider.\n\n**Two Task Definitions (no services):**\n\n- `soci-demo-with-soci` — image tag `latest-soci`\n- `soci-demo-without-soci` — image tag `latest-no-soci`\n- Both: Fargate, awsvpc, runtime platform LINUX\u002FX86_64\n- CPU: `4096` (4 vCPU), Memory: `8192` (8 GB) — needed for PyTorch\n- Health check: `curl -f http:\u002F\u002Flocalhost:8000\u002Fhealth || exit 1`, startPeriod 60s\n- Log driver: awslogs, 7-day retention\n\n**No services, no security groups.** Tasks are launched via `aws ecs run-task` in the comparison script. The user provides subnet IDs and security group at run time (not in Terraform).\n\n**Variables must include:**\n\n- `aws_account_id` (string, validated 12 digits)\n- `aws_region` (string, default \"us-east-1\")\n- `subnet_ids` (list(string) — at least one, used in run-and-compare script)\n- `assign_public_ip` (bool, default false — set true for public subnets without NAT)\n- `cluster_name` (string, default \"soci-demo\")\n- `create_ecr_repository` (bool, default true)\n- `ecr_repository_name` (string, default \"soci-demo-ml-inference\")\n- `image_tag_soci` \u002F `image_tag_no_soci` (strings)\n- `task_cpu` \u002F `task_memory` (strings, defaults \"4096\" \u002F \"8192\")\n- `task_execution_role_arn` (string, optional — used when user has existing roles)\n- `task_role_arn` (string, optional — used when user has existing roles)\n\n**Outputs:** ECR URL, ECR login command (using account ID + region), cluster name, both task definition ARNs, run-task example commands, log group names.\n\n### IAM (terraform\u002Fiam.tf)\n\nGenerate ONLY if user doesn't have existing roles. Two roles:\n\n1. **Task Execution Role** (`soci-demo-task-execution`):\n   - Trust: `ecs-tasks.amazonaws.com`\n   - Attach: `arn:aws:iam::aws:policy\u002Fservice-role\u002FAmazonECSTaskExecutionRolePolicy`\n\n2. **Task Role** (`soci-demo-task`):\n   - Trust: `ecs-tasks.amazonaws.com`\n   - No additional policies (model is baked into image)\n\nIf user provides existing role ARNs, use variables instead and skip iam.tf.\n\n### Build Script (`scripts\u002Fbuild-and-push.sh`)\n\n- Takes args: `\u003CACCOUNT_ID> \u003CREGION> [ECR_REPO_NAME]` (defaults from terraform output)\n- Step 1: `aws ecr get-login-password | docker login`\n- Step 2: `docker build --platform linux\u002Famd64` the image (MUST force amd64 — on Apple Silicon, arm64 builds produce a ~900 MB image with smaller wheels, which is too small to demonstrate SOCI benefit. The x86_64 PyTorch wheels produce a ~6-8 GB image.)\n- Step 3: Tag and push as `latest-soci`\n- Step 4: Tag and push as `latest-no-soci` (same image, different tag)\n- Step 5: Create SOCI **v2** index using `soci convert --standalone` — **no containerd required**:\n  - Pull image from ECR as OCI layout via `skopeo copy` (streams directly — avoids large `docker save` that can crash Docker Desktop)\n  - Run `soci convert --standalone \u003Coci-dir> \u003Coutput-dir> --format oci-dir` to produce a converted OCI layout containing both the image and SOCI index as sibling manifests in an OCI image index\n  - **CRITICAL:** After `soci convert`, patch the output `index.json` with a tag annotation using `jq` — `soci convert --standalone` does NOT preserve the tag reference in the output OCI layout, so `skopeo copy --all oci:\u003Cdir>:\u003Ctag>` will fail with \"no descriptor found for reference\" without this step. Add `org.opencontainers.image.ref.name` annotation to `manifests[0]`.\n  - Push the full OCI index to ECR via `skopeo copy --all` (the `--all` flag is critical — without it, skopeo only pushes one manifest and drops the SOCI index)\n  - **macOS:** Runs soci + skopeo inside a Docker container (`debian:bookworm-slim`, `--platform linux\u002Famd64`, no `--privileged` needed)\n    - Gets ECR password on host via `aws ecr get-login-password` (works with osxkeychain)\n    - No volume mounts of large files — container pulls directly from ECR\n  - **Linux:** Runs soci convert natively (auto-downloads latest if not installed), uses skopeo for push\n  - **Other:** Exits with helpful error and manual instructions\n- Supports `--soci-only` flag to skip build\u002Fpush steps and only recreate the SOCI index (flag must be parsed before positional args to avoid being consumed as ECR_REPO)\n- Always resolves the latest soci version from GitHub API (`\u002Frepos\u002Fawslabs\u002Fsoci-snapshotter\u002Freleases\u002Flatest`)\n- Print next steps (run comparison)\n\n### Run & Compare Script (`scripts\u002Frun-and-compare.sh`)\n\n- Reads subnet IDs and assign_public_ip from `terraform output` (baked in from user input)\n- Takes optional args to override: `[CLUSTER_NAME] [REGION]`\n- Launches two tasks via `aws ecs run-task` (one with-soci task def, one without-soci task def)\n- Passes networking config (`awsvpcConfiguration`) using the subnet from tfvars, default VPC security group, and public IP setting\n- **Does NOT use `aws ecs wait tasks-stopped`** — tasks run indefinitely (FastAPI server). Instead, polls `describe-tasks` for `pullStartedAt`\u002F`pullStoppedAt` at the task level (not container level) until both are populated (max 300s timeout)\n- After collecting pull timing, stops both tasks via `aws ecs stop-task`\n- Calculates pull duration in seconds\n- Prints side-by-side comparison\n- Prints expected ranges (90–180s without SOCI, 15–40s with SOCI for ~6GB image)\n\n### README.md\n\n- What SOCI is (2 sentences)\n- Architecture diagram (ASCII: two tasks pulling from same ECR repo, one with SOCI index)\n- Prerequisites (AWS CLI, Docker, Terraform, soci CLI, jq)\n- Quick start steps (terraform apply → build-and-push → run-and-compare)\n- Expected results table\n- Cleanup commands\n- Limitations\n\n## Comparison Methodology\n\nWith SOCI v2, `latest-soci` is an OCI image index containing two sibling manifests:\n\n1. The image manifest (same layers as `latest-no-soci`)\n2. The SOCI index manifest (`artifactType: application\u002Fvnd.amazon.soci.index.v2+json`) with zTOCs for each layer > 10 MB\n\n`latest-no-soci` is a plain Docker v2 manifest with no SOCI index.\n\nFargate detects the SOCI index via the `com.amazon.soci.index-digest` annotation on the image manifest within the OCI index. If found, it lazy-loads layers on demand. If not found (or if the image is a plain manifest), it does a full sequential pull.\n\nBoth tasks are launched via `aws ecs run-task` (no long-running services). The comparison script runs them, waits for completion, and extracts timing data.\n\nStartup time is measured via ECS task metadata:\n\n- `pullStartedAt` → `pullStoppedAt` = image pull duration\n- These are available in `describe-tasks` output\n\nObserved results for a ~4 GB compressed PyTorch image:\n\n- Without SOCI: ~85 seconds image pull time\n- With SOCI: ~4 seconds image pull time (~21x speedup)\n\n## Anti-Patterns\n\n- **Building on Apple Silicon without `--platform linux\u002Famd64`**: Produces a ~900 MB arm64 image (smaller PyTorch wheels). Too small to show SOCI benefit. Always force `--platform linux\u002Famd64` in the build — Fargate runs x86_64 anyway.\n- **Using SOCI on small images (\u003C500MB)**: Overhead exceeds benefit. SOCI shines on multi-GB images.\n- **Using `soci create` + `soci push` (v1) instead of `soci convert --standalone` (v2)**: v1 requires containerd running, causes issues on macOS\u002FDocker-in-Docker. Use `soci convert --standalone` which has no containerd dependency.\n- **Using `skopeo copy` without `--all`**: Drops the SOCI index manifest from the OCI image index. Must use `skopeo copy --all` to push both the image and SOCI index as sibling manifests.\n- **Pushing `soci convert` output without patching `index.json`**: `soci convert --standalone` does not add `org.opencontainers.image.ref.name` annotations to the output OCI index. Without patching, `skopeo copy --all oci:\u003Cdir>:\u003Ctag>` fails with \"no descriptor found for reference\". Use `jq` to add the tag annotation to `manifests[0]` before pushing.\n- **Using `docker save` for large images on macOS**: Can crash Docker Desktop due to memory pressure. Instead, use `skopeo copy` to pull from ECR directly as an OCI layout.\n- **Using `aws ecs wait tasks-stopped` for comparison**: Tasks run a long-lived server and won't stop on their own. Instead, poll `describe-tasks` for `pullStartedAt`\u002F`pullStoppedAt` fields (task-level, not container-level), then explicitly stop tasks after collecting timing.\n- **Reading pull timing from `containers[0]`**: Pull timing fields (`pullStartedAt`\u002F`pullStoppedAt`) are on the task object itself, not nested under `containers[0]`.\n- **Fargate platform version \u003C 1.4.0**: SOCI requires 1.4.0+.\n- **Expecting SOCI to help with startup logic**: SOCI only reduces image PULL time. Model warm-up is unaffected.\n- **Using :latest tag**: Use explicit tags so you can control which tag has an index.\n\n## Related Skills\n\n- `ecs` — ECS architecture, Fargate configuration, and task definitions\n- `mlops` — ML model deployment patterns on AWS\n- `observability` — CloudWatch metrics and Container Insights for measuring startup times\n- `iam` — Least-privilege task execution and task roles\n- `networking` — VPC endpoints to avoid NAT Gateway costs for ECR\u002FS3 traffic\n",{"data":38,"body":39},{"name":4,"description":6},{"type":40,"children":41},"root",[42,50,55,62,67,76,144,150,184,189,325,338,343,349,362,577,583,597,665,677,682,694,699,760,764,782,808,818,826,906,923,931,1068,1078,1084,1089,1167,1172,1184,1497,1509,1627,1632,1670,1676,1688,1715,1725,1737,1749,1754,1786,1791,1804,1810,2098,2104],{"type":43,"tag":44,"props":45,"children":46},"element","p",{},[47],{"type":48,"value":49},"text","You are an AWS ECS specialist focused on SOCI (Seekable OCI) container image lazy-loading. Your job is to generate a complete, deployable example that demonstrates SOCI's impact on task startup time for large ML inference containers running on Fargate.",{"type":43,"tag":44,"props":51,"children":52},{},[53],{"type":48,"value":54},"You generate all code dynamically based on the user's answers. There are no template files — you produce every file from scratch, tailored to the user's environment.",{"type":43,"tag":56,"props":57,"children":59},"h2",{"id":58},"what-is-soci",[60],{"type":48,"value":61},"What is SOCI?",{"type":43,"tag":44,"props":63,"children":64},{},[65],{"type":48,"value":66},"SOCI (Seekable OCI) enables lazy-loading of container images on Amazon ECS Fargate. Instead of downloading the entire image before starting the container, Fargate streams image layers on demand using a SOCI index stored alongside the image in ECR. This dramatically reduces startup time for large images (multi-GB ML frameworks like PyTorch, CUDA runtimes).",{"type":43,"tag":44,"props":68,"children":69},{},[70],{"type":43,"tag":71,"props":72,"children":73},"strong",{},[74],{"type":48,"value":75},"Key facts:",{"type":43,"tag":77,"props":78,"children":79},"ul",{},[80,86,91,96,116,121,134,139],{"type":43,"tag":81,"props":82,"children":83},"li",{},[84],{"type":48,"value":85},"SOCI v2 produces an OCI image index with two sibling manifests: the image and the SOCI index (containing zTOCs for each large layer)",{"type":43,"tag":81,"props":87,"children":88},{},[89],{"type":48,"value":90},"Only works with images stored in Amazon ECR (same region as the ECS task)",{"type":43,"tag":81,"props":92,"children":93},{},[94],{"type":48,"value":95},"Only works on Fargate platform version 1.4.0+",{"type":43,"tag":81,"props":97,"children":98},{},[99,101,108,110],{"type":48,"value":100},"Use ",{"type":43,"tag":102,"props":103,"children":105},"code",{"className":104},[],[106],{"type":48,"value":107},"soci convert --standalone",{"type":48,"value":109}," (v2) — no containerd required, works on any platform via Docker container. Produces a converted OCI layout that is pushed with ",{"type":43,"tag":102,"props":111,"children":113},{"className":112},[],[114],{"type":48,"value":115},"skopeo copy --all",{"type":43,"tag":81,"props":117,"children":118},{},[119],{"type":48,"value":120},"No application code changes required — completely transparent to the container",{"type":43,"tag":81,"props":122,"children":123},{},[124,126,132],{"type":48,"value":125},"Fargate detects SOCI index via ",{"type":43,"tag":102,"props":127,"children":129},{"className":128},[],[130],{"type":48,"value":131},"com.amazon.soci.index-digest",{"type":48,"value":133}," annotation on the image manifest",{"type":43,"tag":81,"props":135,"children":136},{},[137],{"type":48,"value":138},"Layers smaller than 10 MB don't benefit (download faster than lazy-load overhead)",{"type":43,"tag":81,"props":140,"children":141},{},[142],{"type":48,"value":143},"Observed speedup: ~21x faster pull (4s vs 85s for a ~4 GB compressed PyTorch image)",{"type":43,"tag":56,"props":145,"children":147},{"id":146},"process",[148],{"type":48,"value":149},"Process",{"type":43,"tag":44,"props":151,"children":152},{},[153,158,160,166,168,174,176,182],{"type":43,"tag":71,"props":154,"children":155},{},[156],{"type":48,"value":157},"Important:",{"type":48,"value":159}," This is a task-only demo — no ECS services. We run two standalone tasks (",{"type":43,"tag":102,"props":161,"children":163},{"className":162},[],[164],{"type":48,"value":165},"aws ecs run-task",{"type":48,"value":167},") to compare image pull times with and without SOCI. This means NO VPC, subnet, or security group configuration is needed from the user (tasks use ",{"type":43,"tag":102,"props":169,"children":171},{"className":170},[],[172],{"type":48,"value":173},"awsvpc",{"type":48,"value":175}," networking with the cluster's default settings, or the user provides networking at ",{"type":43,"tag":102,"props":177,"children":179},{"className":178},[],[180],{"type":48,"value":181},"run-task",{"type":48,"value":183}," time).",{"type":43,"tag":44,"props":185,"children":186},{},[187],{"type":48,"value":188},"Before generating anything, gather this information from the user:",{"type":43,"tag":190,"props":191,"children":192},"ol",{},[193,219,229,273,298,308],{"type":43,"tag":81,"props":194,"children":195},{},[196,201,203,209,211,217],{"type":43,"tag":71,"props":197,"children":198},{},[199],{"type":48,"value":200},"Project folder name",{"type":48,"value":202}," — default ",{"type":43,"tag":102,"props":204,"children":206},{"className":205},[],[207],{"type":48,"value":208},"ecs-soci-project",{"type":48,"value":210},", placed in the plugin root (",{"type":43,"tag":102,"props":212,"children":214},{"className":213},[],[215],{"type":48,"value":216},"plugins\u002Faws-dev-toolkit\u002F\u003Cfolder_name>\u002F",{"type":48,"value":218},"). Prompt the user for a custom name or accept the default.",{"type":43,"tag":81,"props":220,"children":221},{},[222,227],{"type":43,"tag":71,"props":223,"children":224},{},[225],{"type":48,"value":226},"AWS account ID",{"type":48,"value":228}," (required — 12 digits, used for ECR login URI)",{"type":43,"tag":81,"props":230,"children":231},{},[232,237,239],{"type":43,"tag":71,"props":233,"children":234},{},[235],{"type":48,"value":236},"IAM roles",{"type":48,"value":238}," — do they have existing ECS task execution and task roles, or should Terraform create them?\n",{"type":43,"tag":77,"props":240,"children":241},{},[242,261],{"type":43,"tag":81,"props":243,"children":244},{},[245,247,253,255],{"type":48,"value":246},"Task execution role needs: trust ",{"type":43,"tag":102,"props":248,"children":250},{"className":249},[],[251],{"type":48,"value":252},"ecs-tasks.amazonaws.com",{"type":48,"value":254},", policy ",{"type":43,"tag":102,"props":256,"children":258},{"className":257},[],[259],{"type":48,"value":260},"AmazonECSTaskExecutionRolePolicy",{"type":43,"tag":81,"props":262,"children":263},{},[264,266,271],{"type":48,"value":265},"Task role needs: trust ",{"type":43,"tag":102,"props":267,"children":269},{"className":268},[],[270],{"type":48,"value":252},{"type":48,"value":272},", no extra policies for this demo",{"type":43,"tag":81,"props":274,"children":275},{},[276,281,283,288,290,296],{"type":43,"tag":71,"props":277,"children":278},{},[279],{"type":48,"value":280},"Subnet ID(s)",{"type":48,"value":282}," — at least one subnet for Fargate tasks (required for ",{"type":43,"tag":102,"props":284,"children":286},{"className":285},[],[287],{"type":48,"value":173},{"type":48,"value":289}," network mode). Default ",{"type":43,"tag":102,"props":291,"children":293},{"className":292},[],[294],{"type":48,"value":295},"assign_public_ip = false",{"type":48,"value":297}," — only set true if user explicitly requests it.",{"type":43,"tag":81,"props":299,"children":300},{},[301,306],{"type":43,"tag":71,"props":302,"children":303},{},[304],{"type":48,"value":305},"ECR",{"type":48,"value":307}," — should Terraform create the repo, or does one exist already?",{"type":43,"tag":81,"props":309,"children":310},{},[311,316,317,323],{"type":43,"tag":71,"props":312,"children":313},{},[314],{"type":48,"value":315},"Region",{"type":48,"value":202},{"type":43,"tag":102,"props":318,"children":320},{"className":319},[],[321],{"type":48,"value":322},"us-east-1",{"type":48,"value":324}," unless they specify otherwise",{"type":43,"tag":44,"props":326,"children":327},{},[328,330,336],{"type":48,"value":329},"Subnet and public IP preference are baked into ",{"type":43,"tag":102,"props":331,"children":333},{"className":332},[],[334],{"type":48,"value":335},"terraform.tfvars",{"type":48,"value":337}," and used as defaults in the run-and-compare script. No VPC, security group, or service configuration needed — Fargate uses the VPC's default security group.",{"type":43,"tag":44,"props":339,"children":340},{},[341],{"type":48,"value":342},"Then generate all files in a single pass.",{"type":43,"tag":56,"props":344,"children":346},{"id":345},"what-to-generate",[347],{"type":48,"value":348},"What to Generate",{"type":43,"tag":44,"props":350,"children":351},{},[352,354,360],{"type":48,"value":353},"Generate these files, writing each one with ",{"type":43,"tag":102,"props":355,"children":357},{"className":356},[],[358],{"type":48,"value":359},"Write",{"type":48,"value":361}," tool:",{"type":43,"tag":363,"props":364,"children":365},"table",{},[366,385],{"type":43,"tag":367,"props":368,"children":369},"thead",{},[370],{"type":43,"tag":371,"props":372,"children":373},"tr",{},[374,380],{"type":43,"tag":375,"props":376,"children":377},"th",{},[378],{"type":48,"value":379},"Path",{"type":43,"tag":375,"props":381,"children":382},{},[383],{"type":48,"value":384},"Purpose",{"type":43,"tag":386,"props":387,"children":388},"tbody",{},[389,407,424,441,458,475,492,509,526,543,560],{"type":43,"tag":371,"props":390,"children":391},{},[392,402],{"type":43,"tag":393,"props":394,"children":395},"td",{},[396],{"type":43,"tag":102,"props":397,"children":399},{"className":398},[],[400],{"type":48,"value":401},"app\u002Fmain.py",{"type":43,"tag":393,"props":403,"children":404},{},[405],{"type":48,"value":406},"FastAPI inference server",{"type":43,"tag":371,"props":408,"children":409},{},[410,419],{"type":43,"tag":393,"props":411,"children":412},{},[413],{"type":43,"tag":102,"props":414,"children":416},{"className":415},[],[417],{"type":48,"value":418},"app\u002Frequirements.txt",{"type":43,"tag":393,"props":420,"children":421},{},[422],{"type":48,"value":423},"Python ML dependencies",{"type":43,"tag":371,"props":425,"children":426},{},[427,436],{"type":43,"tag":393,"props":428,"children":429},{},[430],{"type":43,"tag":102,"props":431,"children":433},{"className":432},[],[434],{"type":48,"value":435},"Dockerfile",{"type":43,"tag":393,"props":437,"children":438},{},[439],{"type":48,"value":440},"Python 3.12 + PyTorch + ML stack",{"type":43,"tag":371,"props":442,"children":443},{},[444,453],{"type":43,"tag":393,"props":445,"children":446},{},[447],{"type":43,"tag":102,"props":448,"children":450},{"className":449},[],[451],{"type":48,"value":452},"terraform\u002Fmain.tf",{"type":43,"tag":393,"props":454,"children":455},{},[456],{"type":48,"value":457},"ECS cluster, two task defs (no services), ECR, log groups",{"type":43,"tag":371,"props":459,"children":460},{},[461,470],{"type":43,"tag":393,"props":462,"children":463},{},[464],{"type":43,"tag":102,"props":465,"children":467},{"className":466},[],[468],{"type":48,"value":469},"terraform\u002Fvariables.tf",{"type":43,"tag":393,"props":471,"children":472},{},[473],{"type":48,"value":474},"All input variables with the user's account ID as default",{"type":43,"tag":371,"props":476,"children":477},{},[478,487],{"type":43,"tag":393,"props":479,"children":480},{},[481],{"type":43,"tag":102,"props":482,"children":484},{"className":483},[],[485],{"type":48,"value":486},"terraform\u002Foutputs.tf",{"type":43,"tag":393,"props":488,"children":489},{},[490],{"type":48,"value":491},"ECR login command, run-task commands, comparison script command",{"type":43,"tag":371,"props":493,"children":494},{},[495,504],{"type":43,"tag":393,"props":496,"children":497},{},[498],{"type":43,"tag":102,"props":499,"children":501},{"className":500},[],[502],{"type":48,"value":503},"terraform\u002Fiam.tf",{"type":43,"tag":393,"props":505,"children":506},{},[507],{"type":48,"value":508},"Execution role + task role (skip if user has existing roles)",{"type":43,"tag":371,"props":510,"children":511},{},[512,521],{"type":43,"tag":393,"props":513,"children":514},{},[515],{"type":43,"tag":102,"props":516,"children":518},{"className":517},[],[519],{"type":48,"value":520},"terraform\u002Fterraform.tfvars",{"type":43,"tag":393,"props":522,"children":523},{},[524],{"type":48,"value":525},"Pre-filled with user's values",{"type":43,"tag":371,"props":527,"children":528},{},[529,538],{"type":43,"tag":393,"props":530,"children":531},{},[532],{"type":43,"tag":102,"props":533,"children":535},{"className":534},[],[536],{"type":48,"value":537},"scripts\u002Fbuild-and-push.sh",{"type":43,"tag":393,"props":539,"children":540},{},[541],{"type":48,"value":542},"Build, push, create SOCI index",{"type":43,"tag":371,"props":544,"children":545},{},[546,555],{"type":43,"tag":393,"props":547,"children":548},{},[549],{"type":43,"tag":102,"props":550,"children":552},{"className":551},[],[553],{"type":48,"value":554},"scripts\u002Frun-and-compare.sh",{"type":43,"tag":393,"props":556,"children":557},{},[558],{"type":48,"value":559},"Run both tasks and compare pull times",{"type":43,"tag":371,"props":561,"children":562},{},[563,572],{"type":43,"tag":393,"props":564,"children":565},{},[566],{"type":43,"tag":102,"props":567,"children":569},{"className":568},[],[570],{"type":48,"value":571},"README.md",{"type":43,"tag":393,"props":573,"children":574},{},[575],{"type":48,"value":576},"Setup instructions",{"type":43,"tag":56,"props":578,"children":580},{"id":579},"code-generation-specifications",[581],{"type":48,"value":582},"Code Generation Specifications",{"type":43,"tag":584,"props":585,"children":587},"h3",{"id":586},"fastapi-app-appmainpy",[588,590,595],{"type":48,"value":589},"FastAPI App (",{"type":43,"tag":102,"props":591,"children":593},{"className":592},[],[594],{"type":48,"value":401},{"type":48,"value":596},")",{"type":43,"tag":77,"props":598,"children":599},{},[600,605,618,647,660],{"type":43,"tag":81,"props":601,"children":602},{},[603],{"type":48,"value":604},"Python 3.12",{"type":43,"tag":81,"props":606,"children":607},{},[608,610,616],{"type":48,"value":609},"Load a HuggingFace model at startup (use ",{"type":43,"tag":102,"props":611,"children":613},{"className":612},[],[614],{"type":48,"value":615},"distilbert-base-uncased-finetuned-sst-2-english",{"type":48,"value":617}," — small enough to bake in, demonstrates real inference)",{"type":43,"tag":81,"props":619,"children":620},{},[621,623,629,631,637,639,645],{"type":48,"value":622},"Endpoints: ",{"type":43,"tag":102,"props":624,"children":626},{"className":625},[],[627],{"type":48,"value":628},"GET \u002Fhealth",{"type":48,"value":630},", ",{"type":43,"tag":102,"props":632,"children":634},{"className":633},[],[635],{"type":48,"value":636},"POST \u002Fpredict",{"type":48,"value":638}," (accepts text, returns label + score), ",{"type":43,"tag":102,"props":640,"children":642},{"className":641},[],[643],{"type":48,"value":644},"GET \u002Fmetrics",{"type":48,"value":646}," (startup time, torch version, cuda status)",{"type":43,"tag":81,"props":648,"children":649},{},[650,652,658],{"type":48,"value":651},"Track ",{"type":43,"tag":102,"props":653,"children":655},{"className":654},[],[656],{"type":48,"value":657},"startup_time",{"type":48,"value":659}," globally so the comparison script can query it",{"type":43,"tag":81,"props":661,"children":662},{},[663],{"type":48,"value":664},"Use FastAPI lifespan context manager for model loading",{"type":43,"tag":584,"props":666,"children":668},{"id":667},"requirements-apprequirementstxt",[669,671,676],{"type":48,"value":670},"Requirements (",{"type":43,"tag":102,"props":672,"children":674},{"className":673},[],[675],{"type":48,"value":418},{"type":48,"value":596},{"type":43,"tag":44,"props":678,"children":679},{},[680],{"type":48,"value":681},"Include these to create a large image (~6–8 GB) that demonstrates SOCI benefit:",{"type":43,"tag":683,"props":684,"children":688},"pre",{"className":685,"code":687,"language":48},[686],"language-text","torch==2.6.0\ntorchvision==0.21.0\ntorchaudio==2.6.0\ntransformers==4.47.0\ntokenizers==0.21.0\nsentencepiece==0.2.0\nsafetensors==0.4.5\ndatasets==3.2.0\naccelerate==1.2.0\nnumpy==2.1.3\nscipy==1.14.1\npandas==2.2.3\nscikit-learn==1.6.0\nopencv-python-headless==4.10.0.84\nPillow==11.0.0\nonnxruntime==1.20.0\nprotobuf==5.29.2\nmatplotlib==3.9.3\nseaborn==0.13.2\nfastapi==0.115.6\nuvicorn[standard]==0.34.0\npydantic==2.10.3\ntqdm==4.67.1\nrequests==2.32.3\nhuggingface-hub==0.27.0\nPyYAML==6.0.2\nfilelock==3.16.1\n",[689],{"type":43,"tag":102,"props":690,"children":692},{"__ignoreMap":691},"",[693],{"type":48,"value":687},{"type":43,"tag":584,"props":695,"children":697},{"id":696},"dockerfile",[698],{"type":48,"value":435},{"type":43,"tag":77,"props":700,"children":701},{},[702,713,718,723,734,739,744,749],{"type":43,"tag":81,"props":703,"children":704},{},[705,707],{"type":48,"value":706},"Base: ",{"type":43,"tag":102,"props":708,"children":710},{"className":709},[],[711],{"type":48,"value":712},"python:3.12-slim",{"type":43,"tag":81,"props":714,"children":715},{},[716],{"type":48,"value":717},"Install system deps (build-essential, curl, git, libgl1, libglib2.0-0)",{"type":43,"tag":81,"props":719,"children":720},{},[721],{"type":48,"value":722},"Copy and install requirements FIRST (large layer = biggest SOCI benefit)",{"type":43,"tag":81,"props":724,"children":725},{},[726,728],{"type":48,"value":727},"Pre-download model weights so startup is deterministic: ",{"type":43,"tag":102,"props":729,"children":731},{"className":730},[],[732],{"type":48,"value":733},"python -c \"from transformers import AutoModelForSequenceClassification, AutoTokenizer; AutoTokenizer.from_pretrained('distilbert-base-uncased-finetuned-sst-2-english'); AutoModelForSequenceClassification.from_pretrained('distilbert-base-uncased-finetuned-sst-2-english')\"",{"type":43,"tag":81,"props":735,"children":736},{},[737],{"type":48,"value":738},"Copy app code LAST (small layer, always pulled immediately)",{"type":43,"tag":81,"props":740,"children":741},{},[742],{"type":48,"value":743},"EXPOSE 8000",{"type":43,"tag":81,"props":745,"children":746},{},[747],{"type":48,"value":748},"HEALTHCHECK using curl to \u002Fhealth",{"type":43,"tag":81,"props":750,"children":751},{},[752,754],{"type":48,"value":753},"CMD: ",{"type":43,"tag":102,"props":755,"children":757},{"className":756},[],[758],{"type":48,"value":759},"uvicorn main:app --host 0.0.0.0 --port 8000 --workers 1",{"type":43,"tag":584,"props":761,"children":762},{"id":19},[763],{"type":48,"value":18},{"type":43,"tag":44,"props":765,"children":766},{},[767,772,774,780],{"type":43,"tag":71,"props":768,"children":769},{},[770],{"type":48,"value":771},"Provider:",{"type":48,"value":773}," AWS, use the latest major version constraint (",{"type":43,"tag":102,"props":775,"children":777},{"className":776},[],[778],{"type":48,"value":779},"~> 6.0",{"type":48,"value":781},"), region from variable.",{"type":43,"tag":44,"props":783,"children":784},{},[785,790,792,798,800,806],{"type":43,"tag":71,"props":786,"children":787},{},[788],{"type":48,"value":789},"ECR:",{"type":48,"value":791}," Create repository (configurable via ",{"type":43,"tag":102,"props":793,"children":795},{"className":794},[],[796],{"type":48,"value":797},"create_ecr_repository",{"type":48,"value":799}," bool). Set ",{"type":43,"tag":102,"props":801,"children":803},{"className":802},[],[804],{"type":48,"value":805},"force_delete = true",{"type":48,"value":807}," for easy cleanup. Enable scan on push.",{"type":43,"tag":44,"props":809,"children":810},{},[811,816],{"type":43,"tag":71,"props":812,"children":813},{},[814],{"type":48,"value":815},"ECS Cluster:",{"type":48,"value":817}," Container Insights enabled. Fargate capacity provider.",{"type":43,"tag":44,"props":819,"children":820},{},[821],{"type":43,"tag":71,"props":822,"children":823},{},[824],{"type":48,"value":825},"Two Task Definitions (no services):",{"type":43,"tag":77,"props":827,"children":828},{},[829,846,862,867,888,901],{"type":43,"tag":81,"props":830,"children":831},{},[832,838,840],{"type":43,"tag":102,"props":833,"children":835},{"className":834},[],[836],{"type":48,"value":837},"soci-demo-with-soci",{"type":48,"value":839}," — image tag ",{"type":43,"tag":102,"props":841,"children":843},{"className":842},[],[844],{"type":48,"value":845},"latest-soci",{"type":43,"tag":81,"props":847,"children":848},{},[849,855,856],{"type":43,"tag":102,"props":850,"children":852},{"className":851},[],[853],{"type":48,"value":854},"soci-demo-without-soci",{"type":48,"value":839},{"type":43,"tag":102,"props":857,"children":859},{"className":858},[],[860],{"type":48,"value":861},"latest-no-soci",{"type":43,"tag":81,"props":863,"children":864},{},[865],{"type":48,"value":866},"Both: Fargate, awsvpc, runtime platform LINUX\u002FX86_64",{"type":43,"tag":81,"props":868,"children":869},{},[870,872,878,880,886],{"type":48,"value":871},"CPU: ",{"type":43,"tag":102,"props":873,"children":875},{"className":874},[],[876],{"type":48,"value":877},"4096",{"type":48,"value":879}," (4 vCPU), Memory: ",{"type":43,"tag":102,"props":881,"children":883},{"className":882},[],[884],{"type":48,"value":885},"8192",{"type":48,"value":887}," (8 GB) — needed for PyTorch",{"type":43,"tag":81,"props":889,"children":890},{},[891,893,899],{"type":48,"value":892},"Health check: ",{"type":43,"tag":102,"props":894,"children":896},{"className":895},[],[897],{"type":48,"value":898},"curl -f http:\u002F\u002Flocalhost:8000\u002Fhealth || exit 1",{"type":48,"value":900},", startPeriod 60s",{"type":43,"tag":81,"props":902,"children":903},{},[904],{"type":48,"value":905},"Log driver: awslogs, 7-day retention",{"type":43,"tag":44,"props":907,"children":908},{},[909,914,916,921],{"type":43,"tag":71,"props":910,"children":911},{},[912],{"type":48,"value":913},"No services, no security groups.",{"type":48,"value":915}," Tasks are launched via ",{"type":43,"tag":102,"props":917,"children":919},{"className":918},[],[920],{"type":48,"value":165},{"type":48,"value":922}," in the comparison script. The user provides subnet IDs and security group at run time (not in Terraform).",{"type":43,"tag":44,"props":924,"children":925},{},[926],{"type":43,"tag":71,"props":927,"children":928},{},[929],{"type":48,"value":930},"Variables must include:",{"type":43,"tag":77,"props":932,"children":933},{},[934,945,956,967,978,989,999,1010,1029,1047,1058],{"type":43,"tag":81,"props":935,"children":936},{},[937,943],{"type":43,"tag":102,"props":938,"children":940},{"className":939},[],[941],{"type":48,"value":942},"aws_account_id",{"type":48,"value":944}," (string, validated 12 digits)",{"type":43,"tag":81,"props":946,"children":947},{},[948,954],{"type":43,"tag":102,"props":949,"children":951},{"className":950},[],[952],{"type":48,"value":953},"aws_region",{"type":48,"value":955}," (string, default \"us-east-1\")",{"type":43,"tag":81,"props":957,"children":958},{},[959,965],{"type":43,"tag":102,"props":960,"children":962},{"className":961},[],[963],{"type":48,"value":964},"subnet_ids",{"type":48,"value":966}," (list(string) — at least one, used in run-and-compare script)",{"type":43,"tag":81,"props":968,"children":969},{},[970,976],{"type":43,"tag":102,"props":971,"children":973},{"className":972},[],[974],{"type":48,"value":975},"assign_public_ip",{"type":48,"value":977}," (bool, default false — set true for public subnets without NAT)",{"type":43,"tag":81,"props":979,"children":980},{},[981,987],{"type":43,"tag":102,"props":982,"children":984},{"className":983},[],[985],{"type":48,"value":986},"cluster_name",{"type":48,"value":988}," (string, default \"soci-demo\")",{"type":43,"tag":81,"props":990,"children":991},{},[992,997],{"type":43,"tag":102,"props":993,"children":995},{"className":994},[],[996],{"type":48,"value":797},{"type":48,"value":998}," (bool, default true)",{"type":43,"tag":81,"props":1000,"children":1001},{},[1002,1008],{"type":43,"tag":102,"props":1003,"children":1005},{"className":1004},[],[1006],{"type":48,"value":1007},"ecr_repository_name",{"type":48,"value":1009}," (string, default \"soci-demo-ml-inference\")",{"type":43,"tag":81,"props":1011,"children":1012},{},[1013,1019,1021,1027],{"type":43,"tag":102,"props":1014,"children":1016},{"className":1015},[],[1017],{"type":48,"value":1018},"image_tag_soci",{"type":48,"value":1020}," \u002F ",{"type":43,"tag":102,"props":1022,"children":1024},{"className":1023},[],[1025],{"type":48,"value":1026},"image_tag_no_soci",{"type":48,"value":1028}," (strings)",{"type":43,"tag":81,"props":1030,"children":1031},{},[1032,1038,1039,1045],{"type":43,"tag":102,"props":1033,"children":1035},{"className":1034},[],[1036],{"type":48,"value":1037},"task_cpu",{"type":48,"value":1020},{"type":43,"tag":102,"props":1040,"children":1042},{"className":1041},[],[1043],{"type":48,"value":1044},"task_memory",{"type":48,"value":1046}," (strings, defaults \"4096\" \u002F \"8192\")",{"type":43,"tag":81,"props":1048,"children":1049},{},[1050,1056],{"type":43,"tag":102,"props":1051,"children":1053},{"className":1052},[],[1054],{"type":48,"value":1055},"task_execution_role_arn",{"type":48,"value":1057}," (string, optional — used when user has existing roles)",{"type":43,"tag":81,"props":1059,"children":1060},{},[1061,1067],{"type":43,"tag":102,"props":1062,"children":1064},{"className":1063},[],[1065],{"type":48,"value":1066},"task_role_arn",{"type":48,"value":1057},{"type":43,"tag":44,"props":1069,"children":1070},{},[1071,1076],{"type":43,"tag":71,"props":1072,"children":1073},{},[1074],{"type":48,"value":1075},"Outputs:",{"type":48,"value":1077}," ECR URL, ECR login command (using account ID + region), cluster name, both task definition ARNs, run-task example commands, log group names.",{"type":43,"tag":584,"props":1079,"children":1081},{"id":1080},"iam-terraformiamtf",[1082],{"type":48,"value":1083},"IAM (terraform\u002Fiam.tf)",{"type":43,"tag":44,"props":1085,"children":1086},{},[1087],{"type":48,"value":1088},"Generate ONLY if user doesn't have existing roles. Two roles:",{"type":43,"tag":190,"props":1090,"children":1091},{},[1092,1134],{"type":43,"tag":81,"props":1093,"children":1094},{},[1095,1100,1102,1108,1110],{"type":43,"tag":71,"props":1096,"children":1097},{},[1098],{"type":48,"value":1099},"Task Execution Role",{"type":48,"value":1101}," (",{"type":43,"tag":102,"props":1103,"children":1105},{"className":1104},[],[1106],{"type":48,"value":1107},"soci-demo-task-execution",{"type":48,"value":1109},"):",{"type":43,"tag":77,"props":1111,"children":1112},{},[1113,1123],{"type":43,"tag":81,"props":1114,"children":1115},{},[1116,1118],{"type":48,"value":1117},"Trust: ",{"type":43,"tag":102,"props":1119,"children":1121},{"className":1120},[],[1122],{"type":48,"value":252},{"type":43,"tag":81,"props":1124,"children":1125},{},[1126,1128],{"type":48,"value":1127},"Attach: ",{"type":43,"tag":102,"props":1129,"children":1131},{"className":1130},[],[1132],{"type":48,"value":1133},"arn:aws:iam::aws:policy\u002Fservice-role\u002FAmazonECSTaskExecutionRolePolicy",{"type":43,"tag":81,"props":1135,"children":1136},{},[1137,1142,1143,1149,1150],{"type":43,"tag":71,"props":1138,"children":1139},{},[1140],{"type":48,"value":1141},"Task Role",{"type":48,"value":1101},{"type":43,"tag":102,"props":1144,"children":1146},{"className":1145},[],[1147],{"type":48,"value":1148},"soci-demo-task",{"type":48,"value":1109},{"type":43,"tag":77,"props":1151,"children":1152},{},[1153,1162],{"type":43,"tag":81,"props":1154,"children":1155},{},[1156,1157],{"type":48,"value":1117},{"type":43,"tag":102,"props":1158,"children":1160},{"className":1159},[],[1161],{"type":48,"value":252},{"type":43,"tag":81,"props":1163,"children":1164},{},[1165],{"type":48,"value":1166},"No additional policies (model is baked into image)",{"type":43,"tag":44,"props":1168,"children":1169},{},[1170],{"type":48,"value":1171},"If user provides existing role ARNs, use variables instead and skip iam.tf.",{"type":43,"tag":584,"props":1173,"children":1175},{"id":1174},"build-script-scriptsbuild-and-pushsh",[1176,1178,1183],{"type":48,"value":1177},"Build Script (",{"type":43,"tag":102,"props":1179,"children":1181},{"className":1180},[],[1182],{"type":48,"value":537},{"type":48,"value":596},{"type":43,"tag":77,"props":1185,"children":1186},{},[1187,1200,1211,1224,1234,1246,1467,1480,1492],{"type":43,"tag":81,"props":1188,"children":1189},{},[1190,1192,1198],{"type":48,"value":1191},"Takes args: ",{"type":43,"tag":102,"props":1193,"children":1195},{"className":1194},[],[1196],{"type":48,"value":1197},"\u003CACCOUNT_ID> \u003CREGION> [ECR_REPO_NAME]",{"type":48,"value":1199}," (defaults from terraform output)",{"type":43,"tag":81,"props":1201,"children":1202},{},[1203,1205],{"type":48,"value":1204},"Step 1: ",{"type":43,"tag":102,"props":1206,"children":1208},{"className":1207},[],[1209],{"type":48,"value":1210},"aws ecr get-login-password | docker login",{"type":43,"tag":81,"props":1212,"children":1213},{},[1214,1216,1222],{"type":48,"value":1215},"Step 2: ",{"type":43,"tag":102,"props":1217,"children":1219},{"className":1218},[],[1220],{"type":48,"value":1221},"docker build --platform linux\u002Famd64",{"type":48,"value":1223}," the image (MUST force amd64 — on Apple Silicon, arm64 builds produce a ~900 MB image with smaller wheels, which is too small to demonstrate SOCI benefit. The x86_64 PyTorch wheels produce a ~6-8 GB image.)",{"type":43,"tag":81,"props":1225,"children":1226},{},[1227,1229],{"type":48,"value":1228},"Step 3: Tag and push as ",{"type":43,"tag":102,"props":1230,"children":1232},{"className":1231},[],[1233],{"type":48,"value":845},{"type":43,"tag":81,"props":1235,"children":1236},{},[1237,1239,1244],{"type":48,"value":1238},"Step 4: Tag and push as ",{"type":43,"tag":102,"props":1240,"children":1242},{"className":1241},[],[1243],{"type":48,"value":861},{"type":48,"value":1245}," (same image, different tag)",{"type":43,"tag":81,"props":1247,"children":1248},{},[1249,1251,1256,1258,1263,1265,1270,1272],{"type":48,"value":1250},"Step 5: Create SOCI ",{"type":43,"tag":71,"props":1252,"children":1253},{},[1254],{"type":48,"value":1255},"v2",{"type":48,"value":1257}," index using ",{"type":43,"tag":102,"props":1259,"children":1261},{"className":1260},[],[1262],{"type":48,"value":107},{"type":48,"value":1264}," — ",{"type":43,"tag":71,"props":1266,"children":1267},{},[1268],{"type":48,"value":1269},"no containerd required",{"type":48,"value":1271},":\n",{"type":43,"tag":77,"props":1273,"children":1274},{},[1275,1296,1309,1373,1393,1447,1457],{"type":43,"tag":81,"props":1276,"children":1277},{},[1278,1280,1286,1288,1294],{"type":48,"value":1279},"Pull image from ECR as OCI layout via ",{"type":43,"tag":102,"props":1281,"children":1283},{"className":1282},[],[1284],{"type":48,"value":1285},"skopeo copy",{"type":48,"value":1287}," (streams directly — avoids large ",{"type":43,"tag":102,"props":1289,"children":1291},{"className":1290},[],[1292],{"type":48,"value":1293},"docker save",{"type":48,"value":1295}," that can crash Docker Desktop)",{"type":43,"tag":81,"props":1297,"children":1298},{},[1299,1301,1307],{"type":48,"value":1300},"Run ",{"type":43,"tag":102,"props":1302,"children":1304},{"className":1303},[],[1305],{"type":48,"value":1306},"soci convert --standalone \u003Coci-dir> \u003Coutput-dir> --format oci-dir",{"type":48,"value":1308}," to produce a converted OCI layout containing both the image and SOCI index as sibling manifests in an OCI image index",{"type":43,"tag":81,"props":1310,"children":1311},{},[1312,1317,1319,1325,1327,1333,1335,1341,1342,1347,1349,1355,1357,1363,1365,1371],{"type":43,"tag":71,"props":1313,"children":1314},{},[1315],{"type":48,"value":1316},"CRITICAL:",{"type":48,"value":1318}," After ",{"type":43,"tag":102,"props":1320,"children":1322},{"className":1321},[],[1323],{"type":48,"value":1324},"soci convert",{"type":48,"value":1326},", patch the output ",{"type":43,"tag":102,"props":1328,"children":1330},{"className":1329},[],[1331],{"type":48,"value":1332},"index.json",{"type":48,"value":1334}," with a tag annotation using ",{"type":43,"tag":102,"props":1336,"children":1338},{"className":1337},[],[1339],{"type":48,"value":1340},"jq",{"type":48,"value":1264},{"type":43,"tag":102,"props":1343,"children":1345},{"className":1344},[],[1346],{"type":48,"value":107},{"type":48,"value":1348}," does NOT preserve the tag reference in the output OCI layout, so ",{"type":43,"tag":102,"props":1350,"children":1352},{"className":1351},[],[1353],{"type":48,"value":1354},"skopeo copy --all oci:\u003Cdir>:\u003Ctag>",{"type":48,"value":1356}," will fail with \"no descriptor found for reference\" without this step. Add ",{"type":43,"tag":102,"props":1358,"children":1360},{"className":1359},[],[1361],{"type":48,"value":1362},"org.opencontainers.image.ref.name",{"type":48,"value":1364}," annotation to ",{"type":43,"tag":102,"props":1366,"children":1368},{"className":1367},[],[1369],{"type":48,"value":1370},"manifests[0]",{"type":48,"value":1372},".",{"type":43,"tag":81,"props":1374,"children":1375},{},[1376,1378,1383,1385,1391],{"type":48,"value":1377},"Push the full OCI index to ECR via ",{"type":43,"tag":102,"props":1379,"children":1381},{"className":1380},[],[1382],{"type":48,"value":115},{"type":48,"value":1384}," (the ",{"type":43,"tag":102,"props":1386,"children":1388},{"className":1387},[],[1389],{"type":48,"value":1390},"--all",{"type":48,"value":1392}," flag is critical — without it, skopeo only pushes one manifest and drops the SOCI index)",{"type":43,"tag":81,"props":1394,"children":1395},{},[1396,1401,1403,1409,1410,1416,1418,1424,1426],{"type":43,"tag":71,"props":1397,"children":1398},{},[1399],{"type":48,"value":1400},"macOS:",{"type":48,"value":1402}," Runs soci + skopeo inside a Docker container (",{"type":43,"tag":102,"props":1404,"children":1406},{"className":1405},[],[1407],{"type":48,"value":1408},"debian:bookworm-slim",{"type":48,"value":630},{"type":43,"tag":102,"props":1411,"children":1413},{"className":1412},[],[1414],{"type":48,"value":1415},"--platform linux\u002Famd64",{"type":48,"value":1417},", no ",{"type":43,"tag":102,"props":1419,"children":1421},{"className":1420},[],[1422],{"type":48,"value":1423},"--privileged",{"type":48,"value":1425}," needed)\n",{"type":43,"tag":77,"props":1427,"children":1428},{},[1429,1442],{"type":43,"tag":81,"props":1430,"children":1431},{},[1432,1434,1440],{"type":48,"value":1433},"Gets ECR password on host via ",{"type":43,"tag":102,"props":1435,"children":1437},{"className":1436},[],[1438],{"type":48,"value":1439},"aws ecr get-login-password",{"type":48,"value":1441}," (works with osxkeychain)",{"type":43,"tag":81,"props":1443,"children":1444},{},[1445],{"type":48,"value":1446},"No volume mounts of large files — container pulls directly from ECR",{"type":43,"tag":81,"props":1448,"children":1449},{},[1450,1455],{"type":43,"tag":71,"props":1451,"children":1452},{},[1453],{"type":48,"value":1454},"Linux:",{"type":48,"value":1456}," Runs soci convert natively (auto-downloads latest if not installed), uses skopeo for push",{"type":43,"tag":81,"props":1458,"children":1459},{},[1460,1465],{"type":43,"tag":71,"props":1461,"children":1462},{},[1463],{"type":48,"value":1464},"Other:",{"type":48,"value":1466}," Exits with helpful error and manual instructions",{"type":43,"tag":81,"props":1468,"children":1469},{},[1470,1472,1478],{"type":48,"value":1471},"Supports ",{"type":43,"tag":102,"props":1473,"children":1475},{"className":1474},[],[1476],{"type":48,"value":1477},"--soci-only",{"type":48,"value":1479}," flag to skip build\u002Fpush steps and only recreate the SOCI index (flag must be parsed before positional args to avoid being consumed as ECR_REPO)",{"type":43,"tag":81,"props":1481,"children":1482},{},[1483,1485,1491],{"type":48,"value":1484},"Always resolves the latest soci version from GitHub API (",{"type":43,"tag":102,"props":1486,"children":1488},{"className":1487},[],[1489],{"type":48,"value":1490},"\u002Frepos\u002Fawslabs\u002Fsoci-snapshotter\u002Freleases\u002Flatest",{"type":48,"value":596},{"type":43,"tag":81,"props":1493,"children":1494},{},[1495],{"type":48,"value":1496},"Print next steps (run comparison)",{"type":43,"tag":584,"props":1498,"children":1500},{"id":1499},"run-compare-script-scriptsrun-and-comparesh",[1501,1503,1508],{"type":48,"value":1502},"Run & Compare Script (",{"type":43,"tag":102,"props":1504,"children":1506},{"className":1505},[],[1507],{"type":48,"value":554},{"type":48,"value":596},{"type":43,"tag":77,"props":1510,"children":1511},{},[1512,1525,1536,1548,1561,1601,1612,1617,1622],{"type":43,"tag":81,"props":1513,"children":1514},{},[1515,1517,1523],{"type":48,"value":1516},"Reads subnet IDs and assign_public_ip from ",{"type":43,"tag":102,"props":1518,"children":1520},{"className":1519},[],[1521],{"type":48,"value":1522},"terraform output",{"type":48,"value":1524}," (baked in from user input)",{"type":43,"tag":81,"props":1526,"children":1527},{},[1528,1530],{"type":48,"value":1529},"Takes optional args to override: ",{"type":43,"tag":102,"props":1531,"children":1533},{"className":1532},[],[1534],{"type":48,"value":1535},"[CLUSTER_NAME] [REGION]",{"type":43,"tag":81,"props":1537,"children":1538},{},[1539,1541,1546],{"type":48,"value":1540},"Launches two tasks via ",{"type":43,"tag":102,"props":1542,"children":1544},{"className":1543},[],[1545],{"type":48,"value":165},{"type":48,"value":1547}," (one with-soci task def, one without-soci task def)",{"type":43,"tag":81,"props":1549,"children":1550},{},[1551,1553,1559],{"type":48,"value":1552},"Passes networking config (",{"type":43,"tag":102,"props":1554,"children":1556},{"className":1555},[],[1557],{"type":48,"value":1558},"awsvpcConfiguration",{"type":48,"value":1560},") using the subnet from tfvars, default VPC security group, and public IP setting",{"type":43,"tag":81,"props":1562,"children":1563},{},[1564,1575,1577,1583,1585,1591,1593,1599],{"type":43,"tag":71,"props":1565,"children":1566},{},[1567,1569],{"type":48,"value":1568},"Does NOT use ",{"type":43,"tag":102,"props":1570,"children":1572},{"className":1571},[],[1573],{"type":48,"value":1574},"aws ecs wait tasks-stopped",{"type":48,"value":1576}," — tasks run indefinitely (FastAPI server). Instead, polls ",{"type":43,"tag":102,"props":1578,"children":1580},{"className":1579},[],[1581],{"type":48,"value":1582},"describe-tasks",{"type":48,"value":1584}," for ",{"type":43,"tag":102,"props":1586,"children":1588},{"className":1587},[],[1589],{"type":48,"value":1590},"pullStartedAt",{"type":48,"value":1592},"\u002F",{"type":43,"tag":102,"props":1594,"children":1596},{"className":1595},[],[1597],{"type":48,"value":1598},"pullStoppedAt",{"type":48,"value":1600}," at the task level (not container level) until both are populated (max 300s timeout)",{"type":43,"tag":81,"props":1602,"children":1603},{},[1604,1606],{"type":48,"value":1605},"After collecting pull timing, stops both tasks via ",{"type":43,"tag":102,"props":1607,"children":1609},{"className":1608},[],[1610],{"type":48,"value":1611},"aws ecs stop-task",{"type":43,"tag":81,"props":1613,"children":1614},{},[1615],{"type":48,"value":1616},"Calculates pull duration in seconds",{"type":43,"tag":81,"props":1618,"children":1619},{},[1620],{"type":48,"value":1621},"Prints side-by-side comparison",{"type":43,"tag":81,"props":1623,"children":1624},{},[1625],{"type":48,"value":1626},"Prints expected ranges (90–180s without SOCI, 15–40s with SOCI for ~6GB image)",{"type":43,"tag":584,"props":1628,"children":1630},{"id":1629},"readmemd",[1631],{"type":48,"value":571},{"type":43,"tag":77,"props":1633,"children":1634},{},[1635,1640,1645,1650,1655,1660,1665],{"type":43,"tag":81,"props":1636,"children":1637},{},[1638],{"type":48,"value":1639},"What SOCI is (2 sentences)",{"type":43,"tag":81,"props":1641,"children":1642},{},[1643],{"type":48,"value":1644},"Architecture diagram (ASCII: two tasks pulling from same ECR repo, one with SOCI index)",{"type":43,"tag":81,"props":1646,"children":1647},{},[1648],{"type":48,"value":1649},"Prerequisites (AWS CLI, Docker, Terraform, soci CLI, jq)",{"type":43,"tag":81,"props":1651,"children":1652},{},[1653],{"type":48,"value":1654},"Quick start steps (terraform apply → build-and-push → run-and-compare)",{"type":43,"tag":81,"props":1656,"children":1657},{},[1658],{"type":48,"value":1659},"Expected results table",{"type":43,"tag":81,"props":1661,"children":1662},{},[1663],{"type":48,"value":1664},"Cleanup commands",{"type":43,"tag":81,"props":1666,"children":1667},{},[1668],{"type":48,"value":1669},"Limitations",{"type":43,"tag":56,"props":1671,"children":1673},{"id":1672},"comparison-methodology",[1674],{"type":48,"value":1675},"Comparison Methodology",{"type":43,"tag":44,"props":1677,"children":1678},{},[1679,1681,1686],{"type":48,"value":1680},"With SOCI v2, ",{"type":43,"tag":102,"props":1682,"children":1684},{"className":1683},[],[1685],{"type":48,"value":845},{"type":48,"value":1687}," is an OCI image index containing two sibling manifests:",{"type":43,"tag":190,"props":1689,"children":1690},{},[1691,1702],{"type":43,"tag":81,"props":1692,"children":1693},{},[1694,1696,1701],{"type":48,"value":1695},"The image manifest (same layers as ",{"type":43,"tag":102,"props":1697,"children":1699},{"className":1698},[],[1700],{"type":48,"value":861},{"type":48,"value":596},{"type":43,"tag":81,"props":1703,"children":1704},{},[1705,1707,1713],{"type":48,"value":1706},"The SOCI index manifest (",{"type":43,"tag":102,"props":1708,"children":1710},{"className":1709},[],[1711],{"type":48,"value":1712},"artifactType: application\u002Fvnd.amazon.soci.index.v2+json",{"type":48,"value":1714},") with zTOCs for each layer > 10 MB",{"type":43,"tag":44,"props":1716,"children":1717},{},[1718,1723],{"type":43,"tag":102,"props":1719,"children":1721},{"className":1720},[],[1722],{"type":48,"value":861},{"type":48,"value":1724}," is a plain Docker v2 manifest with no SOCI index.",{"type":43,"tag":44,"props":1726,"children":1727},{},[1728,1730,1735],{"type":48,"value":1729},"Fargate detects the SOCI index via the ",{"type":43,"tag":102,"props":1731,"children":1733},{"className":1732},[],[1734],{"type":48,"value":131},{"type":48,"value":1736}," annotation on the image manifest within the OCI index. If found, it lazy-loads layers on demand. If not found (or if the image is a plain manifest), it does a full sequential pull.",{"type":43,"tag":44,"props":1738,"children":1739},{},[1740,1742,1747],{"type":48,"value":1741},"Both tasks are launched via ",{"type":43,"tag":102,"props":1743,"children":1745},{"className":1744},[],[1746],{"type":48,"value":165},{"type":48,"value":1748}," (no long-running services). The comparison script runs them, waits for completion, and extracts timing data.",{"type":43,"tag":44,"props":1750,"children":1751},{},[1752],{"type":48,"value":1753},"Startup time is measured via ECS task metadata:",{"type":43,"tag":77,"props":1755,"children":1756},{},[1757,1774],{"type":43,"tag":81,"props":1758,"children":1759},{},[1760,1765,1767,1772],{"type":43,"tag":102,"props":1761,"children":1763},{"className":1762},[],[1764],{"type":48,"value":1590},{"type":48,"value":1766}," → ",{"type":43,"tag":102,"props":1768,"children":1770},{"className":1769},[],[1771],{"type":48,"value":1598},{"type":48,"value":1773}," = image pull duration",{"type":43,"tag":81,"props":1775,"children":1776},{},[1777,1779,1784],{"type":48,"value":1778},"These are available in ",{"type":43,"tag":102,"props":1780,"children":1782},{"className":1781},[],[1783],{"type":48,"value":1582},{"type":48,"value":1785}," output",{"type":43,"tag":44,"props":1787,"children":1788},{},[1789],{"type":48,"value":1790},"Observed results for a ~4 GB compressed PyTorch image:",{"type":43,"tag":77,"props":1792,"children":1793},{},[1794,1799],{"type":43,"tag":81,"props":1795,"children":1796},{},[1797],{"type":48,"value":1798},"Without SOCI: ~85 seconds image pull time",{"type":43,"tag":81,"props":1800,"children":1801},{},[1802],{"type":48,"value":1803},"With SOCI: ~4 seconds image pull time (~21x speedup)",{"type":43,"tag":56,"props":1805,"children":1807},{"id":1806},"anti-patterns",[1808],{"type":48,"value":1809},"Anti-Patterns",{"type":43,"tag":77,"props":1811,"children":1812},{},[1813,1835,1845,1885,1913,1970,1993,2028,2063,2073,2083],{"type":43,"tag":81,"props":1814,"children":1815},{},[1816,1826,1828,1833],{"type":43,"tag":71,"props":1817,"children":1818},{},[1819,1821],{"type":48,"value":1820},"Building on Apple Silicon without ",{"type":43,"tag":102,"props":1822,"children":1824},{"className":1823},[],[1825],{"type":48,"value":1415},{"type":48,"value":1827},": Produces a ~900 MB arm64 image (smaller PyTorch wheels). Too small to show SOCI benefit. Always force ",{"type":43,"tag":102,"props":1829,"children":1831},{"className":1830},[],[1832],{"type":48,"value":1415},{"type":48,"value":1834}," in the build — Fargate runs x86_64 anyway.",{"type":43,"tag":81,"props":1836,"children":1837},{},[1838,1843],{"type":43,"tag":71,"props":1839,"children":1840},{},[1841],{"type":48,"value":1842},"Using SOCI on small images (\u003C500MB)",{"type":48,"value":1844},": Overhead exceeds benefit. SOCI shines on multi-GB images.",{"type":43,"tag":81,"props":1846,"children":1847},{},[1848,1876,1878,1883],{"type":43,"tag":71,"props":1849,"children":1850},{},[1851,1853,1859,1861,1867,1869,1874],{"type":48,"value":1852},"Using ",{"type":43,"tag":102,"props":1854,"children":1856},{"className":1855},[],[1857],{"type":48,"value":1858},"soci create",{"type":48,"value":1860}," + ",{"type":43,"tag":102,"props":1862,"children":1864},{"className":1863},[],[1865],{"type":48,"value":1866},"soci push",{"type":48,"value":1868}," (v1) instead of ",{"type":43,"tag":102,"props":1870,"children":1872},{"className":1871},[],[1873],{"type":48,"value":107},{"type":48,"value":1875}," (v2)",{"type":48,"value":1877},": v1 requires containerd running, causes issues on macOS\u002FDocker-in-Docker. Use ",{"type":43,"tag":102,"props":1879,"children":1881},{"className":1880},[],[1882],{"type":48,"value":107},{"type":48,"value":1884}," which has no containerd dependency.",{"type":43,"tag":81,"props":1886,"children":1887},{},[1888,1904,1906,1911],{"type":43,"tag":71,"props":1889,"children":1890},{},[1891,1892,1897,1899],{"type":48,"value":1852},{"type":43,"tag":102,"props":1893,"children":1895},{"className":1894},[],[1896],{"type":48,"value":1285},{"type":48,"value":1898}," without ",{"type":43,"tag":102,"props":1900,"children":1902},{"className":1901},[],[1903],{"type":48,"value":1390},{"type":48,"value":1905},": Drops the SOCI index manifest from the OCI image index. Must use ",{"type":43,"tag":102,"props":1907,"children":1909},{"className":1908},[],[1910],{"type":48,"value":115},{"type":48,"value":1912}," to push both the image and SOCI index as sibling manifests.",{"type":43,"tag":81,"props":1914,"children":1915},{},[1916,1933,1935,1940,1942,1947,1949,1954,1956,1961,1963,1968],{"type":43,"tag":71,"props":1917,"children":1918},{},[1919,1921,1926,1928],{"type":48,"value":1920},"Pushing ",{"type":43,"tag":102,"props":1922,"children":1924},{"className":1923},[],[1925],{"type":48,"value":1324},{"type":48,"value":1927}," output without patching ",{"type":43,"tag":102,"props":1929,"children":1931},{"className":1930},[],[1932],{"type":48,"value":1332},{"type":48,"value":1934},": ",{"type":43,"tag":102,"props":1936,"children":1938},{"className":1937},[],[1939],{"type":48,"value":107},{"type":48,"value":1941}," does not add ",{"type":43,"tag":102,"props":1943,"children":1945},{"className":1944},[],[1946],{"type":48,"value":1362},{"type":48,"value":1948}," annotations to the output OCI index. Without patching, ",{"type":43,"tag":102,"props":1950,"children":1952},{"className":1951},[],[1953],{"type":48,"value":1354},{"type":48,"value":1955}," fails with \"no descriptor found for reference\". Use ",{"type":43,"tag":102,"props":1957,"children":1959},{"className":1958},[],[1960],{"type":48,"value":1340},{"type":48,"value":1962}," to add the tag annotation to ",{"type":43,"tag":102,"props":1964,"children":1966},{"className":1965},[],[1967],{"type":48,"value":1370},{"type":48,"value":1969}," before pushing.",{"type":43,"tag":81,"props":1971,"children":1972},{},[1973,1984,1986,1991],{"type":43,"tag":71,"props":1974,"children":1975},{},[1976,1977,1982],{"type":48,"value":1852},{"type":43,"tag":102,"props":1978,"children":1980},{"className":1979},[],[1981],{"type":48,"value":1293},{"type":48,"value":1983}," for large images on macOS",{"type":48,"value":1985},": Can crash Docker Desktop due to memory pressure. Instead, use ",{"type":43,"tag":102,"props":1987,"children":1989},{"className":1988},[],[1990],{"type":48,"value":1285},{"type":48,"value":1992}," to pull from ECR directly as an OCI layout.",{"type":43,"tag":81,"props":1994,"children":1995},{},[1996,2007,2009,2014,2015,2020,2021,2026],{"type":43,"tag":71,"props":1997,"children":1998},{},[1999,2000,2005],{"type":48,"value":1852},{"type":43,"tag":102,"props":2001,"children":2003},{"className":2002},[],[2004],{"type":48,"value":1574},{"type":48,"value":2006}," for comparison",{"type":48,"value":2008},": Tasks run a long-lived server and won't stop on their own. Instead, poll ",{"type":43,"tag":102,"props":2010,"children":2012},{"className":2011},[],[2013],{"type":48,"value":1582},{"type":48,"value":1584},{"type":43,"tag":102,"props":2016,"children":2018},{"className":2017},[],[2019],{"type":48,"value":1590},{"type":48,"value":1592},{"type":43,"tag":102,"props":2022,"children":2024},{"className":2023},[],[2025],{"type":48,"value":1598},{"type":48,"value":2027}," fields (task-level, not container-level), then explicitly stop tasks after collecting timing.",{"type":43,"tag":81,"props":2029,"children":2030},{},[2031,2042,2044,2049,2050,2055,2057,2062],{"type":43,"tag":71,"props":2032,"children":2033},{},[2034,2036],{"type":48,"value":2035},"Reading pull timing from ",{"type":43,"tag":102,"props":2037,"children":2039},{"className":2038},[],[2040],{"type":48,"value":2041},"containers[0]",{"type":48,"value":2043},": Pull timing fields (",{"type":43,"tag":102,"props":2045,"children":2047},{"className":2046},[],[2048],{"type":48,"value":1590},{"type":48,"value":1592},{"type":43,"tag":102,"props":2051,"children":2053},{"className":2052},[],[2054],{"type":48,"value":1598},{"type":48,"value":2056},") are on the task object itself, not nested under ",{"type":43,"tag":102,"props":2058,"children":2060},{"className":2059},[],[2061],{"type":48,"value":2041},{"type":48,"value":1372},{"type":43,"tag":81,"props":2064,"children":2065},{},[2066,2071],{"type":43,"tag":71,"props":2067,"children":2068},{},[2069],{"type":48,"value":2070},"Fargate platform version \u003C 1.4.0",{"type":48,"value":2072},": SOCI requires 1.4.0+.",{"type":43,"tag":81,"props":2074,"children":2075},{},[2076,2081],{"type":43,"tag":71,"props":2077,"children":2078},{},[2079],{"type":48,"value":2080},"Expecting SOCI to help with startup logic",{"type":48,"value":2082},": SOCI only reduces image PULL time. Model warm-up is unaffected.",{"type":43,"tag":81,"props":2084,"children":2085},{},[2086,2096],{"type":43,"tag":71,"props":2087,"children":2088},{},[2089,2090,2094],{"type":48,"value":1852},{"type":43,"tag":2091,"props":2092,"children":2093},"latest",{},[],{"type":48,"value":2095}," tag",{"type":48,"value":2097},": Use explicit tags so you can control which tag has an index.",{"type":43,"tag":56,"props":2099,"children":2101},{"id":2100},"related-skills",[2102],{"type":48,"value":2103},"Related Skills",{"type":43,"tag":77,"props":2105,"children":2106},{},[2107,2118,2129,2140,2151],{"type":43,"tag":81,"props":2108,"children":2109},{},[2110,2116],{"type":43,"tag":102,"props":2111,"children":2113},{"className":2112},[],[2114],{"type":48,"value":2115},"ecs",{"type":48,"value":2117}," — ECS architecture, Fargate configuration, and task definitions",{"type":43,"tag":81,"props":2119,"children":2120},{},[2121,2127],{"type":43,"tag":102,"props":2122,"children":2124},{"className":2123},[],[2125],{"type":48,"value":2126},"mlops",{"type":48,"value":2128}," — ML model deployment patterns on AWS",{"type":43,"tag":81,"props":2130,"children":2131},{},[2132,2138],{"type":43,"tag":102,"props":2133,"children":2135},{"className":2134},[],[2136],{"type":48,"value":2137},"observability",{"type":48,"value":2139}," — CloudWatch metrics and Container Insights for measuring startup times",{"type":43,"tag":81,"props":2141,"children":2142},{},[2143,2149],{"type":43,"tag":102,"props":2144,"children":2146},{"className":2145},[],[2147],{"type":48,"value":2148},"iam",{"type":48,"value":2150}," — Least-privilege task execution and task roles",{"type":43,"tag":81,"props":2152,"children":2153},{},[2154,2160],{"type":43,"tag":102,"props":2155,"children":2157},{"className":2156},[],[2158],{"type":48,"value":2159},"networking",{"type":48,"value":2161}," — VPC endpoints to avoid NAT Gateway costs for ECR\u002FS3 traffic",{"items":2163,"total":2261},[2164,2178,2193,2205,2217,2232,2246],{"slug":2165,"name":2165,"fn":2166,"description":2167,"org":2168,"tags":2169,"stars":26,"repoUrl":27,"updatedAt":2177},"agentcore","design Amazon Bedrock AgentCore architectures","Deep-dive into Amazon Bedrock AgentCore platform design, service selection, deployment, and production operations. This skill should be used when the user asks to \"design an AgentCore architecture\", \"deploy agents on AgentCore\", \"configure AgentCore Runtime\", \"set up AgentCore Memory\", \"use AgentCore Gateway\", \"configure AgentCore Identity\", \"set up AgentCore Policy\", \"plan agent observability\", \"evaluate agent quality\", \"move agent PoC to production\", or mentions AgentCore, AgentCore Runtime, AgentCore Memory, AgentCore Gateway, AgentCore Identity, AgentCore Policy, AgentCore Evaluations, AgentCore Code Interpreter, AgentCore Browser, A2A protocol, or multi-agent orchestration on AWS.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2170,2173,2176],{"name":2171,"slug":2172,"type":16},"Agents","agents",{"name":2174,"slug":2175,"type":16},"Architecture","architecture",{"name":24,"slug":25,"type":16},"2026-07-12T08:40:11.108951",{"slug":2179,"name":2179,"fn":2180,"description":2181,"org":2182,"tags":2183,"stars":26,"repoUrl":27,"updatedAt":2192},"aidlc-lite","develop AI applications on AWS","Lightweight AI development lifecycle for building on AWS. A simplified take on the AI-DLC philosophy — think together, then build fast. Acts as a design partner that understands intent, proposes alternatives with trade-offs, and ships working code without the ceremony of full requirements\u002Fdesign\u002Fspec documents. Use when a founder says \"build X on AWS\", \"add Y to my stack\", \"scaffold an API\", or \"write the CDK for Z\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2184,2185,2188,2189],{"name":2171,"slug":2172,"type":16},{"name":2186,"slug":2187,"type":16},"AI Infrastructure","ai-infrastructure",{"name":24,"slug":25,"type":16},{"name":2190,"slug":2191,"type":16},"Engineering","engineering","2026-07-12T08:40:40.204103",{"slug":2194,"name":2194,"fn":2195,"description":2196,"org":2197,"tags":2198,"stars":26,"repoUrl":27,"updatedAt":2204},"architect-for-startups","advise on AWS architecture for startups","AWS architecture advisor tailored specifically for startups. Alters AWS architecture recommendations based on startup stage (pre-revenue through Series B+), team size, runway, and credits. ALWAYS use when asked about building on AWS, choosing services, planning infrastructure, managing costs with credits, or preparing architecture for fundraising.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2199,2200,2201],{"name":2174,"slug":2175,"type":16},{"name":24,"slug":25,"type":16},{"name":2202,"slug":2203,"type":16},"Strategy","strategy","2026-07-12T08:41:33.557354",{"slug":2206,"name":2206,"fn":2207,"description":2208,"org":2209,"tags":2210,"stars":26,"repoUrl":27,"updatedAt":2216},"aws-architect","design and review AWS architectures","Design and review AWS architectures following Well-Architected Framework principles. Use when planning new infrastructure, reviewing existing architectures, evaluating trade-offs between AWS services, or when asked about AWS best practices.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2211,2212,2213],{"name":2174,"slug":2175,"type":16},{"name":24,"slug":25,"type":16},{"name":2214,"slug":2215,"type":16},"Infrastructure","infrastructure","2026-07-12T08:40:57.630086",{"slug":2218,"name":2218,"fn":2219,"description":2220,"org":2221,"tags":2222,"stars":26,"repoUrl":27,"updatedAt":2231},"aws-compare","compare AWS architecture options","Compare 2-3 AWS architecture options side-by-side across cost, complexity, performance, security, and operational burden. Use when evaluating trade-offs between approaches or when the user is deciding between options.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2223,2224,2225,2228],{"name":2174,"slug":2175,"type":16},{"name":24,"slug":25,"type":16},{"name":2226,"slug":2227,"type":16},"Cost Optimization","cost-optimization",{"name":2229,"slug":2230,"type":16},"Security","security","2026-07-12T08:40:23.960287",{"slug":2233,"name":2233,"fn":2234,"description":2235,"org":2236,"tags":2237,"stars":26,"repoUrl":27,"updatedAt":2245},"aws-debug","debug AWS infrastructure and deployment failures","Debug AWS infrastructure issues, deployment failures, and runtime errors. Use when troubleshooting CloudFormation stack failures, Lambda errors, ECS task failures, permission issues, networking problems, or any AWS service misbehavior.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2238,2239,2242,2243],{"name":24,"slug":25,"type":16},{"name":2240,"slug":2241,"type":16},"Debugging","debugging",{"name":14,"slug":15,"type":16},{"name":2244,"slug":2137,"type":16},"Observability","2026-07-12T08:40:16.767171",{"slug":2247,"name":2247,"fn":2248,"description":2249,"org":2250,"tags":2251,"stars":26,"repoUrl":27,"updatedAt":2260},"aws-diagram","generate AWS architecture diagrams","Generate AWS architecture diagrams in Mermaid or ASCII from a description, existing IaC, or conversation context. Use when the user wants to visualize an architecture.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2252,2253,2254,2257],{"name":2174,"slug":2175,"type":16},{"name":24,"slug":25,"type":16},{"name":2255,"slug":2256,"type":16},"Diagrams","diagrams",{"name":2258,"slug":2259,"type":16},"Visualization","visualization","2026-07-12T08:40:43.26341",42,{"items":2263,"total":2435},[2264,2279,2300,2310,2323,2336,2346,2356,2375,2390,2405,2420],{"slug":2265,"name":2265,"fn":2266,"description":2267,"org":2268,"tags":2269,"stars":2276,"repoUrl":2277,"updatedAt":2278},"agentcore-investigation","investigate Bedrock AgentCore runtime sessions","Investigate Bedrock AgentCore runtime sessions via CloudWatch Logs Insights — resolve session\u002Ftrace IDs, query OTEL spans, filter noise, build timelines. Use when debugging AgentCore agent sessions, tracing tool calls, or analyzing latency.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2270,2271,2272,2275],{"name":24,"slug":25,"type":16},{"name":2240,"slug":2241,"type":16},{"name":2273,"slug":2274,"type":16},"Logs","logs",{"name":2244,"slug":2137,"type":16},9427,"https:\u002F\u002Fgithub.com\u002Fawslabs\u002Fmcp","2026-07-12T08:37:22.601527",{"slug":2280,"name":2281,"fn":2282,"description":2283,"org":2284,"tags":2285,"stars":2276,"repoUrl":2277,"updatedAt":2299},"amazon-aurora-dsql","amazon aurora dsql","build applications with Aurora DSQL","Build with Aurora DSQL — manage schemas, execute queries, handle migrations, diagnose query plans, load data, and develop applications with a serverless, distributed SQL database. Covers IAM auth, multi-tenant patterns, MySQL-to-DSQL and PostgreSQL-to-DSQL schema conversion, FK replacement code generation, OCC retry patterns, ORM migration (Django\u002FHibernate\u002FRails), DDL operations, query plan explainability, SQL compatibility validation, and bulk data loading. Triggers on phrases like: DSQL, Aurora DSQL, create DSQL table, DSQL schema, migrate to DSQL, distributed SQL database, serverless PostgreSQL-compatible database, DSQL query plan, DSQL EXPLAIN ANALYZE, why is my DSQL query slow, DSQL foreign key, DSQL OCC retry, DSQL multi-region, load into DSQL, load CSV into DSQL, bulk load DSQL, aurora-dsql-loader.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2286,2289,2290,2293,2296],{"name":2287,"slug":2288,"type":16},"Aurora","aurora",{"name":24,"slug":25,"type":16},{"name":2291,"slug":2292,"type":16},"Database","database",{"name":2294,"slug":2295,"type":16},"Serverless","serverless",{"name":2297,"slug":2298,"type":16},"SQL","sql","2026-07-12T08:36:45.053393",{"slug":2301,"name":2302,"fn":2282,"description":2283,"org":2303,"tags":2304,"stars":2276,"repoUrl":2277,"updatedAt":2309},"aurora-dsql","aurora dsql",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2305,2306,2307,2308],{"name":24,"slug":25,"type":16},{"name":2291,"slug":2292,"type":16},{"name":2294,"slug":2295,"type":16},{"name":2297,"slug":2298,"type":16},"2026-07-12T08:36:42.694299",{"slug":2311,"name":2312,"fn":2282,"description":2283,"org":2313,"tags":2314,"stars":2276,"repoUrl":2277,"updatedAt":2322},"aws-dsql","aws dsql",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2315,2316,2317,2320,2321],{"name":24,"slug":25,"type":16},{"name":2291,"slug":2292,"type":16},{"name":2318,"slug":2319,"type":16},"Migration","migration",{"name":2294,"slug":2295,"type":16},{"name":2297,"slug":2298,"type":16},"2026-07-12T08:36:38.584057",{"slug":2324,"name":2325,"fn":2282,"description":2283,"org":2326,"tags":2327,"stars":2276,"repoUrl":2277,"updatedAt":2335},"distributed-postgres","distributed postgres",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2328,2329,2330,2333,2334],{"name":24,"slug":25,"type":16},{"name":2291,"slug":2292,"type":16},{"name":2331,"slug":2332,"type":16},"PostgreSQL","postgresql",{"name":2294,"slug":2295,"type":16},{"name":2297,"slug":2298,"type":16},"2026-07-12T08:36:46.530743",{"slug":2337,"name":2338,"fn":2282,"description":2283,"org":2339,"tags":2340,"stars":2276,"repoUrl":2277,"updatedAt":2345},"distributed-sql","distributed sql",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2341,2342,2343,2344],{"name":24,"slug":25,"type":16},{"name":2291,"slug":2292,"type":16},{"name":2294,"slug":2295,"type":16},{"name":2297,"slug":2298,"type":16},"2026-07-12T08:36:48.104182",{"slug":2347,"name":2347,"fn":2282,"description":2283,"org":2348,"tags":2349,"stars":2276,"repoUrl":2277,"updatedAt":2355},"dsql",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2350,2351,2352,2353,2354],{"name":24,"slug":25,"type":16},{"name":2291,"slug":2292,"type":16},{"name":2318,"slug":2319,"type":16},{"name":2294,"slug":2295,"type":16},{"name":2297,"slug":2298,"type":16},"2026-07-12T08:36:36.374512",{"slug":2357,"name":2357,"fn":2358,"description":2359,"org":2360,"tags":2361,"stars":2372,"repoUrl":2373,"updatedAt":2374},"cost-efficiency-analyzer","analyze cost efficiency and expenses","Analyzes cost structure, cost efficiency, and expense management from P&L data. Use when the user asks about costs, expenses, COGS, operating expenses, cost ratios, cost control, spending efficiency, margin compression from cost side, or wants to understand where money is going. Also use for \"are we spending too much\", \"cost breakdown\", \"expense analysis\", or \"how efficient are our operations\". NOT for revenue or top-line analysis.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2362,2365,2368,2369],{"name":2363,"slug":2364,"type":16},"Accounting","accounting",{"name":2366,"slug":2367,"type":16},"Analytics","analytics",{"name":2226,"slug":2227,"type":16},{"name":2370,"slug":2371,"type":16},"Finance","finance",3176,"https:\u002F\u002Fgithub.com\u002Fawslabs\u002Fagentcore-samples","2026-07-12T08:40:03.29555",{"slug":2376,"name":2376,"fn":2377,"description":2378,"org":2379,"tags":2380,"stars":2372,"repoUrl":2373,"updatedAt":2389},"executive-financial-briefing","generate executive financial briefings","Generates a concise executive-level financial briefing or summary suitable for a CEO, CFO, or board presentation. Use when the user asks for a summary, briefing, executive summary, board update, financial overview, financial health check, or \"how is the business doing\". Covers the full P&L picture in one page. Also use for \"give me the highlights\", \"what do I need to know\", or \"quick financial update\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2381,2382,2383,2386],{"name":24,"slug":25,"type":16},{"name":2370,"slug":2371,"type":16},{"name":2384,"slug":2385,"type":16},"Management","management",{"name":2387,"slug":2388,"type":16},"Reporting","reporting","2026-07-12T08:40:02.066471",{"slug":2391,"name":2391,"fn":2392,"description":2393,"org":2394,"tags":2395,"stars":2372,"repoUrl":2373,"updatedAt":2404},"multi-quarter-trend-analysis","analyze multi-quarter financial trends","Analyzes financial trends across multiple quarters by comparing P&L metrics over time. Use when the user wants to see trends, patterns, trajectories, or directional movement across 3 or more quarters. Also use for \"how are we trending\", \"show me the trend\", \"track performance over time\", \"quarter over quarter comparison across all quarters\", or any multi-period longitudinal analysis.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2396,2397,2398,2401],{"name":2366,"slug":2367,"type":16},{"name":2370,"slug":2371,"type":16},{"name":2399,"slug":2400,"type":16},"Financial Statements","financial-statements",{"name":2402,"slug":2403,"type":16},"Variance Analysis","variance-analysis","2026-07-12T08:40:00.79141",{"slug":2406,"name":2406,"fn":2407,"description":2408,"org":2409,"tags":2410,"stars":2372,"repoUrl":2373,"updatedAt":2419},"pdf","process and manipulate PDF documents","Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text\u002Ftables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting\u002Fdecrypting PDFs, extracting images, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2411,2414,2417],{"name":2412,"slug":2413,"type":16},"Automation","automation",{"name":2415,"slug":2416,"type":16},"Documents","documents",{"name":2418,"slug":2406,"type":16},"PDF","2026-07-12T08:41:44.135656",{"slug":2421,"name":2421,"fn":2422,"description":2423,"org":2424,"tags":2425,"stars":2372,"repoUrl":2373,"updatedAt":2434},"quarterly-kpi-calculator","calculate quarterly financial KPIs","Calculates quarterly financial KPIs from P&L data. P&L figures can be provided directly by the user or fetched from the financial data MCP server. Use when the user wants KPI calculations such as Gross Margin %, EBITDA Margin %, Operating Expense Ratio, or Revenue Growth % QoQ. Also use for quarterly performance review, P&L analysis, or interpreting financial ratios against benchmarks.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2426,2427,2430,2431],{"name":2363,"slug":2364,"type":16},{"name":2428,"slug":2429,"type":16},"Data Analysis","data-analysis",{"name":2370,"slug":2371,"type":16},{"name":2432,"slug":2433,"type":16},"KPI","kpi","2026-07-12T08:39:59.54971",150]