What Is an AMI and How to Create One from Your EC2 Instance

You've spent hours configuring an EC2 instance — installing packages, tuning configs, setting up your application stack — and now you need a repeatable, reliable way to stamp out identical instances on demand. That's exactly the problem Amazon Machine Images (AMIs) solve.

TL;DR

ConceptWhat It Means
AMIA snapshot-backed template containing the OS, software, and configuration needed to launch an EC2 instance
EBS SnapshotThe underlying point-in-time copy of each EBS volume attached to your instance; AMIs reference these
AMI Region ScopeAMIs are regional; you must copy them to other regions to use them there
No-Reboot OptionAllows AMI creation without stopping the instance, but risks filesystem inconsistency
Launch TemplateReferences an AMI ID to automate and version-control instance launches

What Exactly Is an AMI?

An AMI is a regional, immutable template that EC2 uses to launch instances. It bundles three things:

  • Root volume snapshot — the OS disk (EBS-backed or, less commonly, instance-store-backed)
  • Block device mapping — defines which EBS snapshots to attach and at which device paths
  • Launch permissions — controls which AWS accounts can use the AMI (private by default)

When you launch an instance from an AMI, EC2 creates fresh EBS volumes from those snapshots and boots the instance. The AMI itself is never modified — it's a blueprint, not a running resource.

Analogy: Think of an AMI like a master VM image in VMware or a Docker image in a container registry. The running EC2 instance is the container; the AMI is the image it was born from. You can spin up 100 identical containers from one image without touching the original.

AMI Lifecycle: From Instance to Image to New Instance

graph LR A["Configured EC2 Instance"] -->|"CreateImage API"| B["AWS Stops Instance (or No-Reboot)"] B --> C["EBS Snapshots Created"] C --> D["AMI Registered ami-xxxxxxxx"] D --> E["New Instance Launch"] E --> F["Fresh EBS Volumes Hydrated from Snapshots"] F --> G["Identical Running EC2 Instance"]
  1. Configured EC2 Instance: Your golden instance with all software and settings in place.
  2. CreateImage API call: AWS stops (or optionally keeps running) the instance, flushes the filesystem, and takes EBS snapshots of all attached volumes.
  3. AMI Registration: AWS registers the AMI with a unique ami-xxxxxxxxxxxxxxxxx ID, linking it to the underlying snapshots.
  4. EBS Snapshots: Stored independently in S3 (managed by AWS, not directly visible in your S3 console). These are what you're billed for.
  5. New Instance Launch: EC2 hydrates fresh volumes from the snapshots and boots a new, identical instance.

Step 1: Prepare Your Instance (Best Practices Before Creating an AMI)

Before triggering the image creation, harden your golden instance to avoid baking in secrets or stale state:

  • Remove SSH authorized keys and credentials if this AMI will be shared or used in Auto Scaling.
  • Clear shell history: history -c && history -w
  • Remove temporary files and logs to reduce snapshot size.
  • If on Linux, consider running sudo cloud-init clean --logs so cloud-init re-runs on first boot of new instances.
  • Ensure your application is in a consistent state (flush writes, close DB connections if applicable).

Step 2: Create the AMI

Option A — AWS Management Console

  1. Navigate to EC2 → Instances, select your instance.
  2. Click Actions → Image and templates → Create image.
  3. Provide an Image name (e.g., my-app-golden-v1) and optional description.
  4. Review the Block device mappings — add, remove, or resize volumes as needed.
  5. Choose whether to enable No reboot (see warning below).
  6. Click Create image. The AMI status will show pending until snapshots complete.

Option B — AWS CLI

🔽 [Click to expand] — AWS CLI: Create AMI
# Replace with your actual instance ID
INSTANCE_ID="i-0abc1234def567890"

aws ec2 create-image \
  --instance-id "$INSTANCE_ID" \
  --name "my-app-golden-v1" \
  --description "Golden AMI for my-app, configured 2025-07" \
  --no-reboot \
  --tag-specifications \
    'ResourceType=image,Tags=[{Key=Name,Value=my-app-golden-v1},{Key=Environment,Value=production}]' \
    'ResourceType=snapshot,Tags=[{Key=Name,Value=my-app-golden-v1-snapshot}]'

# Poll until AMI is available
aws ec2 wait image-available --image-ids ami-xxxxxxxxxxxxxxxxx

⚠️ No-Reboot Warning: The --no-reboot flag skips stopping the instance before snapshotting. This avoids downtime but risks capturing an inconsistent filesystem state — similar to pulling a hard power plug on a running server. For stateless or read-heavy workloads it's often acceptable; for databases or write-heavy apps, prefer a clean stop.

Option C — AWS SDK (Python / Boto3)

🔽 [Click to expand] — Boto3: Create AMI
import boto3

ec2 = boto3.client("ec2", region_name="us-east-1")

response = ec2.create_image(
    InstanceId="i-0abc1234def567890",
    Name="my-app-golden-v1",
    Description="Golden AMI for my-app, configured 2025-07",
    NoReboot=False,  # Recommended: stop instance for consistency
    TagSpecifications=[
        {
            "ResourceType": "image",
            "Tags": [
                {"Key": "Name", "Value": "my-app-golden-v1"},
                {"Key": "Environment", "Value": "production"},
            ],
        },
        {
            "ResourceType": "snapshot",
            "Tags": [{"Key": "Name", "Value": "my-app-golden-v1-snapshot"}],
        },
    ],
)

ami_id = response["ImageId"]
print(f"AMI creation initiated: {ami_id}")

# Wait for AMI to become available
waiter = ec2.get_waiter("image_available")
waiter.wait(ImageIds=[ami_id])
print(f"AMI {ami_id} is now available.")

Step 3: Verify the AMI

aws ec2 describe-images \
  --owners self \
  --filters "Name=name,Values=my-app-golden-v1" \
  --query "Images[*].{ID:ImageId,State:State,Created:CreationDate}" \
  --output table

Wait for State to show available before attempting to launch instances from it.

Step 4: Launch a New Instance from Your AMI

🔽 [Click to expand] — AWS CLI: Launch instance from AMI
aws ec2 run-instances \
  --image-id ami-xxxxxxxxxxxxxxxxx \
  --instance-type t3.medium \
  --key-name my-key-pair \
  --security-group-ids sg-0abc1234def567890 \
  --subnet-id subnet-0abc1234def567890 \
  --iam-instance-profile Name=my-instance-profile \
  --count 1 \
  --tag-specifications \
    'ResourceType=instance,Tags=[{Key=Name,Value=my-app-from-ami}]'

AMI Sharing and Cross-Region Copy

AMIs are private and regional by default. Here's how to extend their reach:

graph TD AMI["AMI ami-xxxxxxxx us-east-1"] --> P["Private (Default - Your Account Only)"] AMI --> S["Shared (Specific AWS Account IDs)"] AMI --> PUB["Public (All AWS Accounts - Use with Caution)"] AMI -->|"copy-image API"| CR["Copied AMI ami-yyyyyyyy eu-west-1"]
  1. Private (default): Only your AWS account can use the AMI.
  2. Shared with specific accounts: Grant launch permissions to trusted account IDs without making the AMI public.
  3. Public: Any AWS account can launch instances from it. Use with caution — never bake secrets into a public AMI.
  4. Cross-Region Copy: The copy-image API replicates the AMI and its underlying snapshots to a target region, generating a new AMI ID in that region.
🔽 [Click to expand] — Copy AMI to another region
# Copy AMI from us-east-1 to eu-west-1
aws ec2 copy-image \
  --source-region us-east-1 \
  --source-image-id ami-xxxxxxxxxxxxxxxxx \
  --region eu-west-1 \
  --name "my-app-golden-v1-eu" \
  --description "Cross-region copy for EU deployment"

AMI Cost Considerations

You are not billed for the AMI registration itself. Costs come from:

  • EBS Snapshots: You pay for the storage consumed by the snapshots backing the AMI. Snapshots are incremental after the first one.
  • Cross-region data transfer: Copying an AMI to another region incurs data transfer charges.

Pricing and exact limits vary — always check the official AWS EBS pricing page.

AMI Deregistration and Cleanup

Deregistering an AMI does not automatically delete its backing snapshots. You must do both steps explicitly to stop incurring storage costs:

# Step 1: Deregister the AMI
aws ec2 deregister-image --image-id ami-xxxxxxxxxxxxxxxxx

# Step 2: Delete the backing snapshot(s)
# First, find snapshot IDs from the AMI's block device mapping BEFORE deregistering
aws ec2 delete-snapshot --snapshot-id snap-xxxxxxxxxxxxxxxxx

Pro tip: Always record snapshot IDs from describe-images before deregistering, since the association is lost afterward.

Production Pattern: AMI + Launch Template + Auto Scaling

graph LR GA["Golden AMI ami-xxxxxxxx"] --> LT["Launch Template v1, v2, v3..."] LT --> ASG["Auto Scaling Group"] ASG --> I1["EC2 Instance 1"] ASG --> I2["EC2 Instance 2"] ASG --> I3["EC2 Instance N"] PIPE["EC2 Image Builder Pipeline"] -->|"Produces new AMI"| GA
  1. Golden AMI: Your hardened, tested image artifact.
  2. Launch Template: References the AMI ID and defines instance type, security groups, IAM role, and user data. Version-controlled.
  3. Auto Scaling Group: Uses the Launch Template to automatically scale out identical instances under load.
  4. AMI Pipeline (optional): Use EC2 Image Builder to automate AMI creation, patching, and testing on a schedule.

Glossary

TermDefinition
AMI (Amazon Machine Image)A regional template containing OS, software, and block device mappings used to launch EC2 instances
EBS SnapshotA point-in-time, incremental backup of an EBS volume stored durably by AWS
Golden AMIAn industry term for a hardened, pre-configured AMI used as the authoritative base image for production deployments
Launch TemplateAn EC2 resource that stores launch parameters (AMI ID, instance type, etc.) and supports versioning
EC2 Image BuilderAn AWS managed service for automating the creation, maintenance, and testing of AMIs on a pipeline

Next Steps

Related Posts

Comments

Popular posts from this blog

EC2 No Internet Access in Custom VPC: Attaching an Internet Gateway and Fixing Route Tables

EC2 SSH Connection Timeout: The Exact Security Group Rules You Need to Fix It

IAM User vs. IAM Role: Why Your EC2 Instance Should Never Use a User