Immutable Infrastructure
Build immutable infrastructure with versioned machine images and containers to eliminate configuration drift and ensure reproducible deployments.
Note: This guide follows English-language naming conventions and terminology standards common in international development teams. Examples use English identifiers and comments to maximize compatibility across codebases and tooling.
Overview
Immutable infrastructure treats servers and deployments as disposable artifacts that are never modified after creation. Instead of patching running machines, you build new images from versioned definitions and replace old instances entirely. This eliminates configuration drift, makes rollbacks trivial, and ensures every environment — from development to production — runs identical software stacks. See deployment strategies for rollback patterns and blue-green deployment for zero-downtime swaps.
When to Use
Use this resource when:
- Configuration drift causes “works on my machine” issues across environments
- You need reproducible deployments that can be rolled back by switching AMI IDs
- Auditors require traceable infrastructure changes with version control
- Scaling requires launching identical instances without manual setup
Solution
Packer + AWS AMI Build (JSON)
{
"builders": [{
"type": "amazon-ebs",
"region": "us-east-1",
"source_ami": "ami-12345678",
"instance_type": "t3.micro",
"ssh_username": "ubuntu",
"ami_name": "webapp-{{timestamp}}"
}],
"provisioners": [{
"type": "shell",
"script": "setup.sh"
}, {
"type": "file",
"source": "app.tar.gz",
"destination": "/tmp/app.tar.gz"
}]
}
Dockerfile for Immutable Container
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
USER nodejs
EXPOSE 3000
CMD ["node", "server.js"]
Terraform Blue-Green Deploy with Immutable AMI
resource "aws_launch_template" "app" {
name_prefix = "app-"
image_id = var.ami_id
instance_type = "t3.medium"
tag_specifications {
resource_type = "instance"
tags = {
Name = "app-server"
AMI = var.ami_id
}
}
}
resource "aws_autoscaling_group" "app" {
desired_capacity = 3
max_size = 10
min_size = 2
vpc_zone_identifier = var.subnet_ids
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
}
Explanation
Core principles:
- No SSH access to production: If you can’t log in, you can’t mutate
- Version everything: AMI IDs, container digests, and Terraform states are immutable references
- Phoenix servers: Burn and replace rather than patch in place
- Golden images: Pre-baked OS + application + dependencies as a single artifact
Immutable vs. mutable:
| Aspect | Immutable | Mutable |
|---|---|---|
| Update method | Replace entire instance | Patch running system |
| Rollback | Switch AMI / revert deployment | Undo patches manually |
| Drift | Impossible | Common |
| Startup time | Fast (pre-baked) | Slow (provisioning) |
| Storage | Read-only rootfs | Writable everywhere |
Variants
| Technology | Use Case | Notable Features |
|---|---|---|
| Packer | Multi-cloud images | One config → AWS, GCP, Azure, VMware |
| Docker | Container images | Layer caching; registries |
| NixOS | Reproducible OS | Declarative system config; rollbacks |
| Flatcar | Container-optimized OS | Automatic updates; read-only /usr |
| Bottlerocket | AWS container OS | Minimal attack surface; API-driven |
Best Practices
- Store images in registries: ECR, GCR, ACR, or Docker Hub with immutable tags
- Scan images before deploy: Trivy, Clair, or Snyk in CI pipeline. For a dedicated guide, see container security scanning.
- Tag images with git SHA:
myapp:abc1234links artifacts to source code - Use read-only root filesystems: Containers that can’t write can’t be easily compromised
- Separate data from code: Attach EBS volumes or use S3 for state; never store state in the image
Common Mistakes
- Mutable containers: Running
apt-get installinside a running container defeats immutability - Latest tags:
:latestis mutable and non-deterministic; always pin digests or SHAs - Storing secrets in images: Bake credentials into AMIs and containers create permanent exposure. Follow secrets management best practices.
- Forgetting data volumes: Read-only rootfs means logs and uploads need external storage
- No image lifecycle policy: Old images accumulate storage costs and become security liabilities
Frequently Asked Questions
Q: Is immutable infrastructure more expensive? A: Slightly higher storage for images, but lower operational cost due to eliminated drift-related incidents.
Q: How do I handle emergency patches? A: Build a new image with the patch, deploy it, and decommission old instances. The process is identical to normal deployments.
Q: Can I use immutable infrastructure with databases? A: For stateless app servers, yes. For databases, use immutable configuration + persistent data volumes, not immutable data. Learn more in database design.
Related Resources
Docker for Developers — A Complete Guide
Learn Docker from the ground up: images, containers, Dockerfiles, networks, volumes, and Docker Compose for local development.
RecipeDeploy Containers to AWS ECS with Fargate
How to deploy Docker containers to AWS ECS using Fargate serverless compute with Terraform and GitHub Actions
RecipeDocker Basics
How to containerize an application, write a Dockerfile, and run containers with Docker Compose.
RecipeLocal Microservices Development with Docker Compose
Orchestrate multi-service local environments with Docker Compose including databases, caches, message brokers, and reverse proxies with hot reload and shared networks
DocAPI Status Page Template
A template for a public API status page that communicates uptime, incidents, and maintenance windows to consumers.