Home / AWS

AWSCheat sheetIntermediate

EC2 AMI lifecycle cheat sheet: create, copy, share, deprecate and deregister without orphaned snapshots

Commands for the whole AMI lifecycle - create and copy images, share them safely, deprecate old ones, protect golden images, and deregister AMIs together with their snapshots.

Deepak Bhardwaj7 min read

Applies toAmazon EC2 EBS-backed AMIs, AWS CLI v2, Recycle Bin for EC2 AMIs

When you need this

AMIs build up quietly. Each one keeps EBS snapshots that you keep paying for. Teams deregister an AMI and forget the snapshots, share an image with the wrong account, or delete a golden image that an Auto Scaling group still launches from. This cheat sheet covers the commands for each stage. Everything here assumes EBS-backed AMIs and AWS CLI v2.

Set your Region once so the examples stay short:

export AWS_REGION=eu-west-1

Create an AMI

# Default: EC2 reboots the instance to get a consistent file system
aws ec2 create-image \
  --instance-id i-0123456789abcdef0 \
  --name "app-web-2026-11-02" \
  --description "Web tier golden image" \
  --tag-specifications 'ResourceType=image,Tags=[{Key=Owner,Value=platform},{Key=Purpose,Value=golden}]' \
                       'ResourceType=snapshot,Tags=[{Key=Owner,Value=platform}]'

# Wait until it is usable
aws ec2 wait image-available --image-ids ami-0abc1234def567890

Warning

create-image reboots the instance unless you pass --no-reboot. On a production server that is a short outage. With --no-reboot you get a crash-consistent image only, so flush or stop the application yourself for databases.

Tag both the image and the snapshots when you create them. Without snapshot tags, cleaning up later means guessing.

Find what you own

# All your AMIs, newest first, including deprecated ones
aws ec2 describe-images --owners self --include-deprecated \
  --query 'sort_by(Images,&CreationDate)[::-1].[ImageId,Name,CreationDate,DeprecationTime,State]' \
  --output table

# Snapshots behind one AMI
aws ec2 describe-images --image-ids ami-0abc1234def567890 \
  --query 'Images[].BlockDeviceMappings[].Ebs.SnapshotId' --output text

# When was it last used to launch an instance?
aws ec2 describe-image-attribute --image-id ami-0abc1234def567890 \
  --attribute lastLaunchedTime

lastLaunchedTime is updated with a delay, so treat it as a rough signal. Before you delete anything, check live references.

Is anything still using this AMI?

AMI=ami-0abc1234def567890

# Running or stopped instances
aws ec2 describe-instances --filters Name=image-id,Values=$AMI \
  --query 'Reservations[].Instances[].[InstanceId,State.Name]' --output text

# Launch templates (check the default and latest versions)
for lt in $(aws ec2 describe-launch-templates --query 'LaunchTemplates[].LaunchTemplateId' --output text); do
  aws ec2 describe-launch-template-versions --launch-template-id $lt \
    --versions '$Latest' '$Default' \
    --query "LaunchTemplateVersions[?LaunchTemplateData.ImageId=='$AMI'].[LaunchTemplateId,VersionNumber]" \
    --output text
done

Also check launch configurations if you still have any, EC2 Image Builder pipelines, SSM parameters that hold AMI IDs, and Terraform or CloudFormation code that hard-codes the ID.

Copy across Regions and accounts

# Copy to another Region (run in the destination Region)
aws ec2 copy-image --region eu-central-1 \
  --source-region eu-west-1 \
  --source-image-id ami-0abc1234def567890 \
  --name "app-web-2026-11-02" \
  --encrypted --kms-key-id alias/ami-dr \
  --copy-image-tags

--encrypted with --kms-key-id re-encrypts the snapshots with a key in the destination Region. You need this if the source uses the AWS managed aws/ebs key and someone in another account will consume the copy. Check that your CLI version supports --copy-image-tags. If it doesn't, tag the copy afterwards.

Share safely

# Share with one account
aws ec2 modify-image-attribute --image-id ami-0abc1234def567890 \
  --launch-permission "Add=[{UserId=111122223333}]"

# Share with an AWS Organization or an OU
aws ec2 modify-image-attribute --image-id ami-0abc1234def567890 \
  --launch-permission "Add=[{OrganizationArn=arn:aws:organizations::123456789012:organization/o-exampleorgid}]"

# Who can launch it?
aws ec2 describe-image-attribute --image-id ami-0abc1234def567890 \
  --attribute launchPermission

# Remove a share
aws ec2 modify-image-attribute --image-id ami-0abc1234def567890 \
  --launch-permission "Remove=[{UserId=111122223333}]"

For encrypted AMIs, the consumer also needs kms:Decrypt, kms:DescribeKey, kms:CreateGrant and kms:ReEncrypt* on the customer managed key. You can't share an AMI encrypted with aws/ebs at all.

Block public sharing account-wide

aws ec2 enable-image-block-public-access \
  --image-block-public-access-state block-new-sharing

aws ec2 get-image-block-public-access-state

Caution

A public AMI exposes everything on the disk, including config files, keys and data. Turn on block public access in every Region you use. It stops new public sharing. It doesn't make existing public AMIs private, so look for them with describe-images --owners self --filters Name=is-public,Values=true.

Protect golden images

# Block deregistration; with cooldown it stays protected for 24 hours after you turn protection off
aws ec2 enable-image-deregistration-protection \
  --image-id ami-0abc1234def567890 --with-cooldown

aws ec2 disable-image-deregistration-protection --image-id ami-0abc1234def567890

Add a Recycle Bin retention rule so a deregistered AMI can be restored for a while:

aws rbin create-rule \
  --resource-type EC2_IMAGE \
  --retention-period RetentionPeriodValue=7,RetentionPeriodUnit=DAYS \
  --description "Keep deregistered AMIs 7 days" \
  --resource-tags ResourceTagKey=Purpose,ResourceTagValue=golden

# Restore
aws ec2 list-images-in-recycle-bin
aws ec2 restore-image-from-recycle-bin --image-id ami-0abc1234def567890

Recycle Bin keeps the AMI but doesn't keep its snapshots. Add a separate rule with --resource-type EBS_SNAPSHOT as well, or a restored AMI may have no snapshots behind it.

Deprecate before you delete

Deprecation hides the AMI from public and shared listings for other accounts. It also tells consumers the image is going away. Instances and launch templates that already use it keep working.

aws ec2 enable-image-deprecation --image-id ami-0abc1234def567890 \
  --deprecate-at "2026-12-31T00:00:00Z"

aws ec2 disable-image-deprecation --image-id ami-0abc1234def567890

A workable policy is to deprecate an image when its replacement is published and deregister it 30 to 90 days later, once nothing references it.

Deregister and remove snapshots

# Deregister and delete the snapshots in one step
aws ec2 deregister-image --image-id ami-0abc1234def567890 \
  --delete-associated-snapshots

If a snapshot is also used by another AMI, it is kept. On older CLI builds without this flag, record the snapshot IDs first, then delete them yourself:

SNAPS=$(aws ec2 describe-images --image-ids $AMI \
  --query 'Images[].BlockDeviceMappings[].Ebs.SnapshotId' --output text)
aws ec2 deregister-image --image-id $AMI
for s in $SNAPS; do aws ec2 delete-snapshot --snapshot-id $s; done

Find snapshots orphaned by earlier deregistrations

AMI snapshots have descriptions like Created by CreateImage(i-...) for ami-.... This lists snapshots whose AMI no longer exists:

aws ec2 describe-images --owners self --include-deprecated \
  --query 'Images[].ImageId' --output text | tr '\t' '\n' | sort > /tmp/amis.txt

aws ec2 describe-snapshots --owner-ids self \
  --query "Snapshots[?contains(Description,'CreateImage')].[SnapshotId,Description]" \
  --output text | while read sid desc; do
    ami=$(echo "$desc" | grep -o 'ami-[0-9a-f]*')
    grep -qx "$ami" /tmp/amis.txt || echo "$sid  orphaned (was $ami)"
  done

Review the list before you delete anything. AWS Backup and Data Lifecycle Manager create snapshots with different descriptions, so this check leaves them out.

Symptom, cause, fix

Symptom Likely cause Fix
InvalidAMIID.NotFound in an ASG activity AMI deregistered or not in this Region Update the launch template to a current AMI. Restore from Recycle Bin if needed
Other account sees the AMI but launch fails with a KMS error Missing key policy grants for the consumer Add the consumer to the CMK key policy, or copy the AMI with their key
Can't share AMI Encrypted with aws/ebs Copy with --encrypted --kms-key-id <CMK> and share the copy
deregister-image fails Deregistration protection is on, or in cooldown Disable protection and wait out the cooldown
Snapshot bill keeps growing Snapshots left after deregistration Run the orphan check above. Use --delete-associated-snapshots from now on

Prevent it next time

  • Build images with EC2 Image Builder or a pipeline that tags image and snapshots with owner, purpose and expiry.
  • Publish the current AMI ID to an SSM parameter and have launch templates resolve it. Then no one hard-codes IDs.
  • Turn on block public access and a Recycle Bin rule for AMIs and snapshots in every Region.
  • Run the in-use and orphan checks monthly, and deprecate before you deregister.