From VM Gallery Images to Docker Images: The Next Step in Infrastructure Reproducibility
In 2012, I wrote about treating Azure VM gallery images as release artifacts — versioned, tested, deployable artifacts that embodied infrastructure state rather than manual configuration procedures. In 2016, containers made the same idea faster, lighter, and more widely applicable. The progression from bare metal to VM images to container images is a coherent story about how the industry has iteratively solved the reproducibility problem, and understanding the progression helps you understand why each step was an improvement over the last.
The Problem Each Layer Was Solving
Bare metal configuration (pre-2010): Infrastructure state lived in the minds of the people who configured the servers and in documentation that was always partially stale. Reproducibility required following a procedure, which introduced execution variance. Two servers built from the same procedure were similar but not identical.
VM images (2010–2015): Infrastructure state moved into the image file. Provisioning from an image was deterministic — every VM from the same image was identical. The limitation: images were large (gigabytes), slow to build (minutes to hours for a full OS capture), and tied to the OS and its complete installed software stack. Updating an image for a security patch required rebuilding the entire image.
Container images (2014–present): The application and its direct dependencies, layered on top of a minimal base OS image, without carrying a full OS per application. Images are small (tens to hundreds of megabytes for most applications), fast to build (seconds to minutes for a layer cache hit), and the layering model means a security patch to the base OS layer propagates to all images that use it without rebuilding each application image from scratch.
What the Progression Actually Improved
The core improvement at each step was scope reduction: what does the artifact have to carry to fully specify the application's runtime environment?
A VM image had to carry the entire OS, all system services, all installed software, and the application. Changing anything about the application required rebuilding that entire stack.
A container image carried only the OS libraries the application needed (from a base image that could be shared across many applications) and the application itself. The host OS kernel was shared. The base image layers were shared across containers. Each application image was only as large as its unique contributions to the stack.
The Build Process Comparison
VM image build (2012 Azure pattern):
- Provision a VM (10 minutes)
- Install OS patches (15–30 minutes)
- Install SQL Server (30 minutes)
- Apply configuration script (5 minutes)
- Sysprep and capture (30 minutes)
- Test provisioned VM from image (10 minutes)
Total: ~90 minutes to build, test, and register a new image version.
Container image build (2016 Docker pattern):
# Build from Dockerfile
docker build -t myapp:v1.2.3 .
# Layer cache means most layers rebuild in milliseconds
# Only changed layers rebuild from scratch
# Total for a cached build: 10-30 seconds
# Total for a full rebuild: 2-5 minutes
# Push to registry
docker push myregistry.azurecr.io/myapp:v1.2.3The time difference wasn't just convenience — it changed the economics of how often you could iterate on infrastructure. A 90-minute image build meant you batched changes. A 30-second build meant you built a new image for every code change, naturally, as part of the CI pipeline.
What Stayed the Same
The underlying principle didn't change. The artifact is the deployable unit. The artifact is version-controlled and immutable. Deployment is applying the artifact to infrastructure, not following a procedure on infrastructure. Rolling back is running the previous artifact, not reversing a procedure.
These principles hold whether the artifact is a 20GB VMDK, a 200MB Docker image, or a 2MB single-binary executable. The container image was a better vehicle for the principle — lighter, faster, more composable — but the principle predated Docker by years.
If you were building and operating infrastructure from VM images in 2012 and applying the same discipline to container images in 2016, you weren't learning a new concept. You were applying a familiar concept with better tooling. And if you're adopting containers now without having internalized why the immutable-artifact model matters, go back and read the VM images post first. The tooling is secondary to the principle. As always, I'm here to help.