What Packer actually is, and how it works
Second entry in the HashiCorp infrastructure series. Terraform/OpenTofu manages the lifecycle of infrastructure over time; Packer's job stops the moment it hands you a finished image. That single-shot, no-state nature is the thing to understand before anything else about it.
The template pieces
Per Packer's own HCL2 template docs, a template is built from a small set of block types:
sourceblocks hold builder-plugin config — which platform to build for (AMI, qcow2, a Proxmox template, a Docker image) and how to reach it.buildblocks tie one or moresources to theprovisionerandpost-processorsteps that turn that source into a finished artifact.provisionerblocks, nested insidebuild, are the steps that configure the machine while it's temporarily running — shell scripts, Ansible, file uploads.post-processorblocks, also nested insidebuild, run after provisioning — compress the result, upload it somewhere, write a manifest.
graph TD
S[source: builder config<br/>AMI, qcow2, Proxmox template...] --> B[build: ties sources<br/>to provisioners/post-processors]
B --> P1[provisioner: shell]
B --> P2[provisioner: Ansible]
B --> P3[provisioner: file upload]
P1 --> PP1[post-processor: compress]
P2 --> PP1
P3 --> PP1
PP1 --> PP2[post-processor: upload / manifest]
This is the same HCL2 language Terraform/OpenTofu uses — same variable/local syntax, same .pkrvars.hcl convention mirroring .tfvars. If the syntax from the previous entry in this series looked familiar, that's why.
What actually happens during a build
sequenceDiagram
actor You
participant Packer
participant Instance as Temporary build instance
participant Artifact as Artifact store
You->>Packer: packer build template.pkr.hcl
Packer->>Instance: launch from the source block
Packer->>Instance: run provisioners (shell, Ansible, etc)
Instance-->>Packer: machine is configured
Packer->>Artifact: run post-processors (compress, upload, manifest)
Packer->>Instance: destroy
Packer-->>You: artifact ready (AMI, qcow2, template, container image)
packer build launches a genuinely real, temporary instance of whatever the source describes, runs every provisioner against it in order — same as configuring any other machine — then runs the post-processor chain against the result, and only then tears the temporary instance down. What survives is the artifact; the instance that built it doesn't.
No state file, on purpose
Terraform/OpenTofu's state file exists because it has to reconcile a running, changing resource against desired config indefinitely. Packer never has that problem: once packer build finishes, there's nothing left for it to track — no drift to detect, because there's no persistent resource left under its management. Run the same template again and it builds a brand-new artifact from scratch; it doesn't diff against the last one. That's also why "updating" a Packer-built image almost always means building a new one and replacing references to it (in a Terraform variable, an autoscaling group's launch template, whatever consumes the artifact) rather than patching the existing image in place.
Where this fits with the rest of the series
The artifact a Packer build produces is exactly the kind of thing a Terraform/OpenTofu resource block references — an AMI ID, a template name — to actually provision infrastructure from. Next up: Nomad, and then how all three tie together.
Created 2026-09-17T19:07:18+02:00, updated 2026-09-27T17:29:34+02:00 · History · Edit