Persistent VMs in Podman: Install Alpine to a Disk Image
Quick one-liner: Create a qcow2 disk image with qemu-img, install Alpine Linux into it, and boot from disk — so your VM survives container restarts.
Why This Matters
Post #2 proved that KVM hardware acceleration is fast. But there's a catch: every time the container stops, the VM state vanishes. The Alpine ISO is read-only — any changes you make inside the VM exist only in RAM. Stop the container and they're gone.
That's fine for a boot-speed demo, but it's not a real VM. A real VM has a disk that persists between runs. The disk lives on the host filesystem, the container is just the runtime, and the two are completely independent. Stop and restart the container as many times as you want — the disk doesn't care.
This post adds that layer. You'll create a qcow2 disk image, boot from ISO + disk to run the Alpine installer, then boot from disk alone to confirm it survived.
Prerequisites
-
qemu:baseimage from Post #1 - Alpine ISO from Post #2 at
~/Downloads/alpine-standard-3.23.3-x86_64.iso -
~/vmdirectory (you'll create it below)
Step 1: Create the VM Directory and Disk Image
First, create a dedicated directory for your VM disk images:
$ mkdir -p ~/vm
Then create the disk image:
$ podman run --rm \
-v ~/vm:/vm:z \
qemu:base \
qemu-img create -f qcow2 /vm/alpine.qcow2 8G
You should see:
Formatting '/vm/alpine.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=8589934592 lazy_refcounts=off refcount_bits=16
What's qcow2? It stands for QEMU Copy-On-Write version 2. The key property is thin provisioning: the file on your host starts tiny (a few hundred KB) and only grows as the VM actually writes data. Specifying 8G sets the maximum size the VM sees, not the space it consumes on disk immediately.
Step 2: Boot from ISO + Disk to Install
Now boot with both the ISO and the disk attached. The -boot d flag tells QEMU to boot from the CD-ROM first:
$ podman run --rm -it \
--device /dev/kvm \
-v ~/vm:/vm:z \
-v ~/Downloads:/iso:z \
qemu:base \
qemu-system-x86_64 \
-enable-kvm -cpu host \
-nographic \
-m 512 \
-cdrom /iso/alpine-standard-3.23.3-x86_64.iso \
-drive file=/vm/alpine.qcow2,format=qcow2 \
-boot d
Alpine will boot from the ISO into a live environment. Log in as root — no password required.
Step 3: Install Alpine
Once you're at the shell, run the Alpine installer:
# setup-alpine
Work through the prompts. Most defaults are fine. The ones that matter:
-
Hostname: anything, e.g.
alpine -
Network:
eth0, DHCP -
Proxy:
none - Root password: set something you'll remember
- Timezone: your choice
- Mirror: pick the fastest (or just press Enter for the default)
-
SSH server:
opensshornone— your call - Setup a user: enter a username — don't skip this; logging in as root is bad practice
- Full name: optional, press Enter to skip
- User password: set one
-
SSH key or URL:
none -
Disk:
sda— this is your qcow2 image -
How to use it:
sys— full system install to disk -
Erase above disk and continue:
y
When the installer finishes, power off:
# poweroff
The container exits. The alpine.qcow2 file on your host now contains a complete Alpine installation.
Step 4: Boot from Disk Only
Drop the ISO flags entirely. The disk knows how to boot now:
$ podman run --rm -it \
--device /dev/kvm \
-v ~/vm:/vm:z \
qemu:base \
qemu-system-x86_64 \
-enable-kvm -cpu host \
-nographic \
-m 512 \
-drive file=/vm/alpine.qcow2,format=qcow2
Alpine boots from the installed disk. Log in with the username you created during setup. Now write a file to prove the disk persists:
$ echo "hello from install" > ~/persistence-test.txt
$ cat ~/persistence-test.txt
hello from install
$ su -
# poweroff
The container exits. Run the exact same boot command again:
$ podman run --rm -it \
--device /dev/kvm \
-v ~/vm:/vm:z \
qemu:base \
qemu-system-x86_64 \
-enable-kvm -cpu host \
-nographic \
-m 512 \
-drive file=/vm/alpine.qcow2,format=qcow2
Log in and check:
$ cat ~/persistence-test.txt
hello from install
The file survived. The container was destroyed and recreated, but the disk image on your host never changed. That's persistence.
Step 5: Why This Persists Across Container Restarts
The container is ephemeral — --rm means Podman deletes it the moment QEMU exits. But the disk image at ~/vm/alpine.qcow2 lives on your host filesystem, completely outside the container lifecycle.
The bind mount (-v ~/vm:/vm:z) is just a path into the host. Writing to /vm/alpine.qcow2 inside the container is writing to ~/vm/alpine.qcow2 on the host. When the container is gone, the file remains.
New Flags at a Glance
| Flag | Where | What It Does |
|---|---|---|
-drive file=/vm/alpine.qcow2,format=qcow2 |
QEMU | Attaches the disk image as a block device (sda inside the VM) |
-boot d |
QEMU | Sets boot order to CD-ROM first; needed during install so Alpine boots from ISO, not the blank disk |
format=qcow2 |
QEMU -drive option |
Tells QEMU the image format explicitly; avoids format auto-detection warnings |
-v ~/vm:/vm:z |
Podman | Bind-mounts the host ~/vm directory; the disk image lives here, not inside the container |
-v ~/Downloads:/iso:z |
Podman | Bind-mounts the ISO directory; only needed during the install step |
What You've Built
- ✅ qcow2 disk image created on the host
- ✅ Alpine Linux installed to disk inside a KVM container
- ✅ VM boots from disk and survives container restarts
- ✅ Host filesystem as the persistence layer
What's Next?
That install took a few minutes of interactive prompts. Every time you want a new Alpine VM, you'd repeat it from scratch.
Post #4: We'll skip the installer entirely by using a cloud image — a pre-built disk image ready to boot in seconds.
This guide is Part 3 of the KVM Virtual Machines on Podman series.
Part 1: Build a KVM-Ready Container Image from Scratch
Part 2: KVM Acceleration in a Rootless Podman Container
Coming up in Part 4: Cloud Images — Skip the Installer, Boot in Seconds
Found this helpful?
- LinkedIn: Share with your network
- Twitter: Tweet about it
- Questions? Drop a comment below or reach out on LinkedIn
Published: 6 Apr 2026
Author: David Tio
Tags: KVM, QEMU, Podman, Virtualization, Containers, Alpine Linux, qcow2, Linux, Tutorial
Series: KVM Virtual Machines on Podman
Word Count: ~750
SEO Metadata:
- Title: Persistent VMs in Podman: Install Alpine to a qcow2 Disk Image (2026)
- Meta Description: Create a qcow2 disk image with qemu-img, install Alpine Linux inside a rootless Podman container, and boot from disk so your VM survives container restarts.
- Target Keywords: qcow2 podman vm, persistent vm podman, qemu-img create qcow2, alpine linux install qemu, podman kvm persistent disk, vm disk image container
- Series: KVM Virtual Machines on Podman
Top comments (0)