π§© What is an AMI (Amazon Machine Image)?
An AMI is a pre-configured template for launching EC2 instances β essentially a packaged server (OS + software + config) ready to boot.
πΉ What's Inside
π₯οΈ Operating system (Linux, Windows)
βοΈ Installed software & apps
π Monitoring tools
π§ Custom configuration
Benefit: faster boot, faster deployment, no manual reinstalling.
ποΈ Types of AMIs
Type | Description | Best for |
|---|---|---|
AWS-provided | e.g. Amazon Linux 2, maintained by AWS | Free, reliable starting point |
Custom | Built from your own configured instance, you maintain it | Reusable, production-ready setups |
Marketplace | Sold by vendors, comes with pre-installed tools (security, databases, etc.) | Ready-made specialized stacks |
π‘ You can even sell your own AMIs on the Marketplace.
π How an AMI Is Created
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Creating an AMI</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Newsreader:wght@500;600;700&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<style>
.infographic-amiflow {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f4f1ea;
--accent: #2563eb;
--accent-2: #1e40af;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--display-font: 'Newsreader', Georgia, serif;
--body-font: 'Inter', system-ui, sans-serif;
background: var(--paper);
color: var(--ink);
font-family: var(--body-font);
max-width: 680px;
margin: 0 auto;
padding: clamp(1.25rem, 5vw, 3rem);
box-sizing: border-box;
}
.infographic-amiflow[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1c1c24;
--accent: #5b8def;
--accent-2: #85a9f5;
--accent-soft:#20293f;
--line: #2c313d;
}
.infographic-amiflow * { box-sizing: border-box; }
.eb-header { margin-bottom: 1rem; }
.eb-header h1 {
font-family: var(--display-font);
font-weight: 600;
font-size: clamp(1.3rem, 4vw, 1.7rem);
margin: 0 0 0.2rem 0;
}
.eb-header p { color: var(--ink-soft); margin: 0; font-size: 0.85rem; }
.play-row { display: flex; justify-content: flex-end; margin-bottom: 0.75rem; }
.play-btn {
font: inherit; font-size: 0.8rem; font-weight: 600;
display: flex; align-items: center; gap: 0.35rem;
background: var(--accent); color: var(--paper);
border: 1px solid var(--accent); border-radius: 999px;
padding: 0.4rem 0.85rem 0.4rem 0.7rem; cursor: pointer;
}
.play-btn:hover { opacity: 0.88; }
.flow {
display: grid;
grid-template-columns: 1fr 20px 1fr 20px 1fr 20px 1fr 20px 1fr;
align-items: start;
}
.flow-step {
grid-row: 1;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
cursor: pointer;
padding: 0.4rem 0.3rem;
border-radius: 10px;
transition: background 0.15s;
}
.flow-step:hover { background: var(--paper-alt); }
.flow-step.is-open { background: var(--accent-soft); }
.flow-step.is-playing .icon-badge { animation: eb-pulse 0.9s ease-in-out infinite; }
@keyframes eb-pulse {
0%, 100% { box-shadow: 0 0 0 0 var(--accent-soft); }
50% { box-shadow: 0 0 0 5px var(--accent-soft); }
}
.icon-badge {
width: 52px; height: 52px;
border-radius: 50%;
background: var(--paper);
border: 1.5px solid var(--line);
display: flex; align-items: center; justify-content: center;
margin-bottom: 0.4rem;
transition: border-color 0.15s, background 0.15s;
}
.flow-step.is-open .icon-badge,
.flow-step:hover .icon-badge { border-color: var(--accent); }
.icon-badge svg { stroke: var(--accent-2); width: 24px; height: 24px; }
.infographic-amiflow[data-theme="dark"] .icon-badge svg { stroke: var(--accent); }
.step-label { font-weight: 600; font-size: 0.8rem; }
.step-num {
font-family: var(--display-font);
color: var(--accent);
font-size: 0.7rem;
font-weight: 600;
margin-bottom: 0.1rem;
}
.step-detail {
display: none;
font-size: 0.74rem;
color: var(--ink-soft);
margin-top: 0.3rem;
max-width: 9rem;
}
.flow-step.is-open .step-detail { display: block; }
.connector {
grid-row: 1;
height: 52px;
display: flex;
align-items: center;
justify-content: center;
color: var(--line);
font-size: 1.1rem;
}
@media (max-width: 640px) {
.flow { grid-template-columns: 1fr; gap: 0.35rem; }
.flow-step { grid-column: 1; grid-row: auto; flex-direction: row; text-align: left; gap: 0.65rem; padding: 0.5rem; }
.connector { display: none; }
.icon-badge { margin-bottom: 0; flex-shrink: 0; }
.step-detail { max-width: none; }
}
</style>
</head>
<body>
<div class="infographic-amiflow">
<div class="play-row">
<button class="play-btn" id="amiPlayBtn">
<svg id="amiPlayIcon" width="12" height="12" viewBox="0 0 14 14" fill="currentColor"><path d="M3 2 L12 7 L3 12 Z"/></svg>
<span id="amiPlayLabel">Play</span>
</button>
</div>
<div class="flow">
<div class="flow-step" data-step="1">
<div class="step-num">01</div>
<div class="icon-badge">
<svg viewBox="0 0 30 30" fill="none" stroke-width="1.6">
<rect x="8" y="8" width="14" height="14" rx="2"/>
<line x1="11" y1="2" x2="11" y2="8"/><line x1="15" y1="2" x2="15" y2="8"/><line x1="19" y1="2" x2="19" y2="8"/>
<line x1="11" y1="22" x2="11" y2="28"/><line x1="15" y1="22" x2="15" y2="28"/><line x1="19" y1="22" x2="19" y2="28"/>
<line x1="2" y1="11" x2="8" y2="11"/><line x1="2" y1="15" x2="8" y2="15"/><line x1="2" y1="19" x2="8" y2="19"/>
<line x1="22" y1="11" x2="28" y2="11"/><line x1="22" y1="15" x2="28" y2="15"/><line x1="22" y1="19" x2="28" y2="19"/>
</svg>
</div>
<div class="step-label">Launch</div>
<div class="step-detail">Spin up a base EC2 instance.</div>
</div>
<div class="connector">β</div>
<div class="flow-step" data-step="2">
<div class="step-num">02</div>
<div class="icon-badge">
<svg viewBox="0 0 30 30" fill="none" stroke-width="1.6" stroke-linejoin="round">
<path d="M15 3 L17.5 8 L23 8.5 L19 12.5 L20 18 L15 15.3 L10 18 L11 12.5 L7 8.5 L12.5 8 Z"/>
<circle cx="15" cy="12" r="3.2"/>
</svg>
</div>
<div class="step-label">Customize</div>
<div class="step-detail">Install apps & configs.</div>
</div>
<div class="connector">β</div>
<div class="flow-step" data-step="3">
<div class="step-num">03</div>
<div class="icon-badge">
<svg viewBox="0 0 30 30" fill="none" stroke-width="1.6">
<rect x="8" y="8" width="14" height="14" rx="2"/>
<rect x="12.5" y="11.5" width="2" height="7" fill="currentColor" stroke="none"/>
<rect x="15.5" y="11.5" width="2" height="7" fill="currentColor" stroke="none"/>
</svg>
</div>
<div class="step-label">Stop</div>
<div class="step-detail">Preserves data integrity.</div>
</div>
<div class="connector">β</div>
<div class="flow-step" data-step="4">
<div class="step-num">04</div>
<div class="icon-badge">
<svg viewBox="0 0 30 30" fill="none" stroke-width="1.6">
<rect x="6" y="6" width="18" height="18" rx="2"/>
<rect x="10" y="10" width="10" height="10" rx="1" stroke-dasharray="2.5 2.2"/>
</svg>
</div>
<div class="step-label">Create AMI</div>
<div class="step-detail">Snapshots the instance as a template.</div>
</div>
<div class="connector">β</div>
<div class="flow-step" data-step="5">
<div class="step-num">05</div>
<div class="icon-badge">
<svg viewBox="0 0 32 30" fill="none" stroke-width="1.5">
<rect x="2" y="9" width="12" height="12" rx="2"/>
<rect x="16" y="4" width="12" height="12" rx="2"/>
<rect x="16" y="18" width="12" height="8" rx="2"/>
</svg>
</div>
<div class="step-label">Deploy</div>
<div class="step-detail">Launch new instances from it.</div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-amiflow')
|| document.querySelector('.infographic-amiflow');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const steps = Array.from(document.querySelectorAll('.flow-step'));
const playBtn = document.getElementById('amiPlayBtn');
const playIcon = document.getElementById('amiPlayIcon');
const playLabel = document.getElementById('amiPlayLabel');
let playTimer = null;
const STEP_MS = 1500;
function openStep(step) {
steps.forEach(s => s.classList.toggle('is-open', s === step));
}
steps.forEach(step => {
step.setAttribute('tabindex', '0');
step.addEventListener('click', () => {
stopPlay();
const wasOpen = step.classList.contains('is-open');
steps.forEach(s => s.classList.remove('is-open'));
if (!wasOpen) step.classList.add('is-open');
});
step.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); step.click(); }
});
});
function stopPlay() {
if (playTimer) { clearInterval(playTimer); playTimer = null; }
steps.forEach(s => s.classList.remove('is-playing'));
playIcon.innerHTML = '<path d="M3 2 L12 7 L3 12 Z"/>';
playLabel.textContent = 'Play';
}
function startPlay() {
let i = 0;
steps.forEach(s => s.classList.remove('is-open', 'is-playing'));
playIcon.innerHTML = '<rect x="3" y="2" width="3" height="10"/><rect x="8" y="2" width="3" height="10"/>';
playLabel.textContent = 'Pause';
function showStep() {
steps.forEach(s => s.classList.remove('is-open', 'is-playing'));
openStep(steps[i]);
steps[i].classList.add('is-playing');
}
showStep();
playTimer = setInterval(() => {
i++;
if (i >= steps.length) {
clearInterval(playTimer);
playTimer = null;
setTimeout(stopPlay, STEP_MS);
return;
}
showStep();
}, STEP_MS);
}
playBtn.addEventListener('click', () => {
if (playTimer) { stopPlay(); } else { startPlay(); }
});
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});Launch an EC2 instance
Customize it (apps, configs)
Stop the instance (preserves data integrity)
Create the AMI
Launch new instances from it
Behind the scenes: creating an AMI automatically creates EBS snapshots β that's how your instance's data gets stored.
π Cross-Region / Cross-AZ Use
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Deploying an AMI Across AZs</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Newsreader:ital,wght@0,600;1,500&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
.infographic-amideploy {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-2: #1e40af;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--muted: #9a968c;
--ok: #15803d;
--ok-soft: #e6f4ea;
--display-font: 'Newsreader', Georgia, serif;
--body-font: 'Inter', system-ui, sans-serif;
background: var(--paper);
color: var(--ink);
font-family: var(--body-font);
max-width: 880px;
margin: 0 auto;
padding: clamp(1.25rem, 5vw, 3rem);
box-sizing: border-box;
line-height: 1.5;
}
.infographic-amideploy[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-2: #7ea3f5;
--accent-soft:#202942;
--line: #2c313d;
--muted: #6b6f7a;
--ok: #4ade80;
--ok-soft: #123322;
}
.infographic-amideploy * { box-sizing: border-box; }
.eb-header { margin-bottom: 1.25rem; }
.eb-header h1 {
font-family: var(--display-font);
font-weight: 600;
font-size: clamp(1.4rem, 4vw, 1.9rem);
margin: 0 0 0.3rem 0;
line-height: 1.25;
}
.eb-header p { color: var(--ink-soft); margin: 0; font-size: 0.9rem; }
.steps {
display: flex;
gap: 0.6rem;
margin-bottom: 1.25rem;
flex-wrap: wrap;
}
.step-btn {
font: inherit;
font-size: 0.85rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 0.5rem;
background: var(--paper-alt);
color: var(--ink-soft);
border: 1px solid var(--line);
border-radius: 999px;
padding: 0.5rem 1rem 0.5rem 0.6rem;
cursor: pointer;
transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.step-btn .step-num {
width: 22px; height: 22px; border-radius: 50%;
background: var(--paper); border: 1px solid var(--line);
display: flex; align-items: center; justify-content: center;
font-size: 0.75rem; flex-shrink: 0;
}
.step-btn.is-active {
background: var(--accent-soft); color: var(--accent); border-color: var(--accent);
}
.step-btn.is-active .step-num { background: var(--accent); color: var(--paper); border-color: var(--accent); }
.step-btn.is-playing { animation: eb-pulse 1s ease-in-out infinite; }
@keyframes eb-pulse {
0%, 100% { box-shadow: 0 0 0 0 var(--accent-soft); }
50% { box-shadow: 0 0 0 5px var(--accent-soft); }
}
.play-btn {
font: inherit;
font-size: 0.85rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 0.4rem;
background: var(--accent);
color: var(--paper);
border: 1px solid var(--accent);
border-radius: 999px;
padding: 0.5rem 1rem 0.5rem 0.8rem;
cursor: pointer;
margin-left: auto;
transition: opacity 0.15s;
}
.play-btn:hover { opacity: 0.88; }
.play-btn svg { flex-shrink: 0; }
.az-diagram { width: 100%; height: auto; display: block; }
.az-diagram text { font-family: var(--body-font); fill: var(--ink); }
.az-diagram .az-label { font-weight: 700; font-size: 20px; }
.az-diagram .ami-label { font-weight: 700; font-size: 20px; }
.az-diagram .step-label { font-weight: 600; font-size: 14px; fill: var(--ink-soft); }
.az-diagram .az-box { fill: none; stroke: var(--line); stroke-width: 1.5; }
.az-diagram .chip { fill: none; stroke: var(--accent); stroke-width: 2; }
.az-diagram .chip-pin { stroke: var(--accent); stroke-width: 2; }
.az-diagram .ami-icon { fill: var(--paper-alt); stroke: var(--accent-2); stroke-width: 2.5; }
.az-diagram .ami-grid { stroke: var(--accent-2); stroke-width: 1.5; }
.az-diagram .conn { stroke: var(--ink-soft); stroke-width: 1.5; fill: none; marker-end: url(#arrowhead); }
.az-diagram .conn.go { stroke: var(--ok); }
.az-diagram [data-min-step] { transition: opacity 0.2s ease; }
.az-diagram .is-hidden { opacity: 0; pointer-events: none; }
.az-diagram .phase-highlight { fill: var(--accent-soft); opacity: 0; transition: opacity 0.25s ease; }
.az-diagram .phase-highlight.is-active-phase { opacity: 1; }
.eb-footer {
margin-top: 1.25rem;
padding: 0.8rem 1rem;
border-left: 3px solid var(--accent);
background: var(--paper-alt);
border-radius: 0 8px 8px 0;
font-size: 0.86rem;
min-height: 1.4em;
}
.eb-footer strong { font-weight: 600; }
@media (prefers-reduced-motion: reduce) {
.infographic-amideploy *, .infographic-amideploy *::before, .infographic-amideploy *::after {
transition-duration: 0.001ms !important;
}
}
</style>
</head>
<body>
<div class="infographic-amideploy">
<div class="steps">
<button class="step-btn is-active" data-step="1"><span class="step-num">1</span>Source Instance</button>
<button class="step-btn" data-step="2"><span class="step-num">2</span>Create AMI</button>
<button class="step-btn" data-step="3"><span class="step-num">3</span>Deploy</button>
<button class="play-btn" id="amiPlayBtn">
<svg id="amiPlayIcon" width="14" height="14" viewBox="0 0 14 14" fill="currentColor"><path d="M3 2 L12 7 L3 12 Z"/></svg>
<span id="amiPlayLabel">Play</span>
</button>
</div>
<svg class="az-diagram" viewBox="0 0 1180 380" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arrowhead" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto">
<path d="M0,0 L8,4 L0,8 Z" fill="var(--ink-soft)"/>
</marker>
<marker id="arrowhead-ok" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto">
<path d="M0,0 L8,4 L0,8 Z" fill="var(--ok)"/>
</marker>
</defs>
<!-- phase highlights (behind everything) -->
<rect class="phase-highlight is-active-phase" data-phase="1" x="10" y="10" width="360" height="360" rx="16"/>
<rect class="phase-highlight" data-phase="2" x="440" y="150" width="290" height="180" rx="16"/>
<rect class="phase-highlight" data-phase="3" x="800" y="10" width="370" height="360" rx="16"/>
<!-- AZ 1a (source) -->
<rect class="az-box" x="20" y="20" width="340" height="340" rx="16"/>
<text class="az-label" x="45" y="60">ap-south-1a</text>
<g transform="translate(155,130)">
<rect class="chip" x="0" y="0" width="60" height="60" rx="6"/>
<line class="chip-pin" x1="15" y1="-9" x2="15" y2="0"/><line class="chip-pin" x1="30" y1="-9" x2="30" y2="0"/><line class="chip-pin" x1="45" y1="-9" x2="45" y2="0"/>
<line class="chip-pin" x1="15" y1="60" x2="15" y2="69"/><line class="chip-pin" x1="30" y1="60" x2="30" y2="69"/><line class="chip-pin" x1="45" y1="60" x2="45" y2="69"/>
<line class="chip-pin" x1="-9" y1="15" x2="0" y2="15"/><line class="chip-pin" x1="-9" y1="30" x2="0" y2="30"/><line class="chip-pin" x1="-9" y1="45" x2="0" y2="45"/>
<line class="chip-pin" x1="60" y1="15" x2="69" y2="15"/><line class="chip-pin" x1="60" y1="30" x2="69" y2="30"/><line class="chip-pin" x1="60" y1="45" x2="69" y2="45"/>
</g>
<!-- Create AMI arrow + icon -->
<path class="conn is-hidden" data-min-step="2" d="M360,205 C400,205 420,205 452,205"/>
<text class="step-label is-hidden" data-min-step="2" x="405" y="192" text-anchor="middle">Create AMI</text>
<g data-min-step="2" class="is-hidden" transform="translate(495,170)">
<text class="ami-label" x="35" y="-15" text-anchor="middle">Custom AMI</text>
<rect class="ami-icon" x="0" y="0" width="70" height="70" rx="8"/>
<line class="ami-grid" x1="35" y1="6" x2="35" y2="64"/>
<line class="ami-grid" x1="6" y1="26" x2="64" y2="26"/>
<line class="ami-grid" x1="6" y1="47" x2="64" y2="47"/>
</g>
<!-- Deploy arrow -->
<path class="conn go is-hidden" data-min-step="3" marker-end="url(#arrowhead-ok)" d="M565,205 C650,205 720,205 795,205"/>
<text class="step-label is-hidden" data-min-step="3" x="680" y="185" text-anchor="middle">Launch from AMI</text>
<!-- AZ 1b (target) -->
<g data-min-step="3" class="is-hidden">
<rect class="az-box" x="820" y="20" width="340" height="340" rx="16"/>
<text class="az-label" x="845" y="60">us-east-1b</text>
<g transform="translate(955,130)">
<rect class="chip" x="0" y="0" width="60" height="60" rx="6"/>
<line class="chip-pin" x1="15" y1="-9" x2="15" y2="0"/><line class="chip-pin" x1="30" y1="-9" x2="30" y2="0"/><line class="chip-pin" x1="45" y1="-9" x2="45" y2="0"/>
<line class="chip-pin" x1="15" y1="60" x2="15" y2="69"/><line class="chip-pin" x1="30" y1="60" x2="30" y2="69"/><line class="chip-pin" x1="45" y1="60" x2="45" y2="69"/>
<line class="chip-pin" x1="-9" y1="15" x2="0" y2="15"/><line class="chip-pin" x1="-9" y1="30" x2="0" y2="30"/><line class="chip-pin" x1="-9" y1="45" x2="0" y2="45"/>
<line class="chip-pin" x1="60" y1="15" x2="69" y2="15"/><line class="chip-pin" x1="60" y1="30" x2="69" y2="30"/><line class="chip-pin" x1="60" y1="45" x2="69" y2="45"/>
</g>
</g>
</svg>
<div class="eb-footer" id="amiFooter">
<strong>Source Instance</strong> β launch and customize an EC2 instance in ap-south-1a.
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-amideploy')
|| document.querySelector('.infographic-amideploy');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const footerText = {
1: '<strong>Source Instance</strong> β launch and customize an EC2 instance in ap-south-1a.',
2: '<strong>Create AMI</strong> β convert the instance into a reusable Custom AMI.',
3: '<strong>Deploy</strong> β launch a new instance from that AMI in us-east-1b.'
};
const buttons = document.querySelectorAll('.step-btn');
const footer = document.getElementById('amiFooter');
const revealEls = document.querySelectorAll('[data-min-step]');
const phaseEls = document.querySelectorAll('.phase-highlight');
const playBtn = document.getElementById('amiPlayBtn');
const playIcon = document.getElementById('amiPlayIcon');
const playLabel = document.getElementById('amiPlayLabel');
let playTimer = null;
const STEP_MS = 1800;
function goToStep(step) {
buttons.forEach(b => b.classList.toggle('is-active', Number(b.dataset.step) === step));
revealEls.forEach(el => {
const min = Number(el.dataset.minStep);
el.classList.toggle('is-hidden', min > step);
});
phaseEls.forEach(el => {
el.classList.toggle('is-active-phase', Number(el.dataset.phase) === step);
});
footer.innerHTML = footerText[step];
}
function currentStep() {
const active = document.querySelector('.step-btn.is-active');
return active ? Number(active.dataset.step) : 1;
}
function stopPlay() {
if (playTimer) { clearInterval(playTimer); playTimer = null; }
buttons.forEach(b => b.classList.remove('is-playing'));
playIcon.innerHTML = '<path d="M3 2 L12 7 L3 12 Z"/>';
playLabel.textContent = 'Play';
}
function startPlay() {
goToStep(1);
buttons[0].classList.add('is-playing');
playIcon.innerHTML = '<rect x="3" y="2" width="3" height="10"/><rect x="8" y="2" width="3" height="10"/>';
playLabel.textContent = 'Pause';
playTimer = setInterval(() => {
const next = currentStep() + 1;
buttons.forEach(b => b.classList.remove('is-playing'));
if (next > 3) {
stopPlay();
return;
}
goToStep(next);
buttons[next - 1].classList.add('is-playing');
if (next === 3) {
setTimeout(stopPlay, STEP_MS);
clearInterval(playTimer);
playTimer = null;
}
}, STEP_MS);
}
buttons.forEach(btn => {
btn.addEventListener('click', () => { stopPlay(); goToStep(Number(btn.dataset.step)); });
});
playBtn.addEventListener('click', () => {
if (playTimer) { stopPlay(); } else { startPlay(); }
});
goToStep(1);
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});AMIs are tied to a region, but you can copy an AMI to another region.
Example flow:
Launch + customize an instance in
ap-south-1aConvert it into an AMI
Launch a new instance from that AMI in
us-east-1b
Result: a replica of your instance running in a different AZ/region.
π§ Key Takeaways
AMI = blueprint of an EC2 instance
Saves time via pre-packaging
Built on EBS snapshots internally
Enables fast scaling, consistent environments, and cross-AZ/region deployment