Configuring servers after launch is slow and fragile. Packer builds pre-configured machine images so every server starts ready to serve traffic. No Chef runs, no Ansible pulls, no 10-minute bootstrap scripts.
How Packer Works
Source Image → Packer Builds VM → Runs Provisioners → Creates Machine Image
(Ubuntu 22.04) (temporary) (install software) (AMI, Azure Image)The resulting image is immutable. Every server launched from it is identical.
HCL Configuration
# web-server.pkr.hcl
packer {
required_plugins {
amazon = {
version = ">= 1.3.0"
source = "github.com/hashicorp/amazon"
}
}
}
source "amazon-ebs" "web" {
ami_name = "web-server-{{timestamp}}"
instance_type = "t3.medium"
region = "eu-west-1"
source_ami_filter {
filters = {
name = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = ["099720109477"] # Canonical
}
ssh_username = "ubuntu"
}
build {
sources = ["source.amazon-ebs.web"]
provisioner "shell" {
inline = [
"sudo apt-get update",
"sudo apt-get install -y nginx nodejs npm",
"sudo systemctl enable nginx",
]
}
provisioner "file" {
source = "nginx.conf"
destination = "/tmp/nginx.conf"
}
provisioner "shell" {
inline = [
"sudo mv /tmp/nginx.conf /etc/nginx/nginx.conf",
"sudo nginx -t",
]
}
}packer init .
packer build web-server.pkr.hcl
# ==> Builds finished: ami-0123456789abcdef0Master this topic with hands-on labs
Go beyond reading — build real projects in sandboxed environments with expert video guidance.
Browse Courses →Multi-Platform Builds
Build for multiple platforms from one config:
source "amazon-ebs" "web" {
ami_name = "web-server-{{timestamp}}"
# ... AWS config
}
source "azure-arm" "web" {
managed_image_name = "web-server-{{timestamp}}"
# ... Azure config
}
source "docker" "web" {
image = "ubuntu:22.04"
commit = true
}
build {
sources = [
"source.amazon-ebs.web",
"source.azure-arm.web",
"source.docker.web",
]
provisioner "shell" {
inline = [
"apt-get update && apt-get install -y nginx",
]
}
}One build produces an AMI, an Azure image, and a Docker image — all identical.
Ansible Provisioner
For complex configuration, use Ansible instead of shell scripts:
provisioner "ansible" {
playbook_file = "ansible/web-server.yml"
extra_arguments = [
"--extra-vars", "env=production",
]
}# ansible/web-server.yml
- hosts: all
become: true
roles:
- common
- nginx
- node-exporter
- security-hardeningGet weekly IT automation tips
Docker, Ansible, Terraform, MLOps — curated insights delivered to your inbox. No spam.
Subscribe Free →CI/CD Integration
# GitHub Actions
jobs:
build-ami:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Packer
uses: hashicorp/setup-packer@main
- name: Init
run: packer init .
- name: Validate
run: packer validate .
- name: Build
run: packer build -var "version=${{ github.sha }}" .
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}Merge to main → Packer builds a new AMI → Terraform references the latest AMI → Deploy.
Variables and Data Sources
variable "app_version" {
type = string
default = "latest"
}
data "amazon-ami" "base" {
filters = {
name = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-*"
}
most_recent = true
owners = ["099720109477"]
}
source "amazon-ebs" "web" {
source_ami = data.amazon-ami.base.id
# ...
}Packer vs Alternatives
| Approach | Speed | Consistency | Drift |
|---|---|---|---|
| Packer (immutable) | Fast launch | Perfect | None |
| Ansible (mutable) | Slow (converge) | Good | Possible |
| Cloud-init | Medium | Good | Possible |
| Manual | Slow | Poor | Guaranteed |
Use Packer for production servers that need to launch fast and be identical. Use Ansible for configuration that changes frequently and cannot be baked into images. Many teams use both: Packer for the base image, Ansible for the provisioner.
---
Ready to go deeper? Master infrastructure automation with hands-on courses at CopyPasteLearn.
Ready to learn by doing?
Stop reading tutorials — start building. Expert video courses with hands-on labs in real sandboxed environments.
Related Articles
Quality vs Cost in DevOps
The quality-cost tradeoff in DevOps is real but misunderstood. Learn why cutting quality to reduce cost usually increases total cost, and how to find.
Tofu vs Terraform Comparison
OpenTofu forked Terraform after the BSL license change. Compare features, compatibility, licensing, and ecosystem to decide which IaC tool fits your team.
Ansible vs Terraform When to Use
Ansible and Terraform solve different infrastructure problems. Learn when to use each, when to use both together, and how they complement each other.
Physical AI and Robotics DevOps
Apply DevOps practices to physical AI and robotics with simulation testing, OTA updates, fleet management, and safety-critical CI/CD pipelines.
Platform Engineering Maturity Model
Assess and evolve your platform engineering practice with a maturity model covering self-service, golden paths, developer experience, and governance.
Platform Engineering vs DevOps
Platform engineering and DevOps solve different problems. Learn how platform teams build internal developer platforms, where DevOps still applies.
Explore topics
Browse more articles on the topics covered here.