| title | Packer Components |
|---|---|
| sidebar_position | 4 |
| sidebar_label | packer |
| sidebar_class_name | command |
| description | Configure Packer components in your Atmos stack manifests for machine image building. |
| id | packer |
import File from '@site/src/components/File' import Intro from '@site/src/components/Intro'
Packer components build machine images (AMIs, VM images, container images) using HashiCorp Packer. They allow you to manage image builds with the same stack-based configuration approach used for Terraform and Helmfile.Packer components support the common configuration sections:
- [`vars`](/stacks/vars)
- Variables passed to packer.
- [`env`](/stacks/env)
- Environment variables during execution.
- [`settings`](/stacks/settings)
- Integrations and metadata.
- [`metadata`](/stacks/components/component-metadata)
- Component behavior and inheritance.
- [`command`](/stacks/command)
- Override packer binary.
- [`hooks`](/stacks/hooks)
- Lifecycle event handlers.
A typical Packer component configuration:
components:
packer:
ami-ubuntu:
metadata:
component: ami-ubuntu
vars:
region: us-east-1
instance_type: t3.medium
source_ami_filter:
name: "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"
owner: "099720109477" # Canonical
ami_name_prefix: "acme-ubuntu"
env:
AWS_PROFILE: acme-prodPacker components are located in the path configured in atmos.yaml:
# atmos.yaml
components:
packer:
base_path: components/packerExample structure:
components/packer/
├── ami-ubuntu/
│ ├── template.pkr.hcl
│ ├── variables.pkr.hcl
│ └── scripts/
│ ├── setup.sh
│ └── cleanup.sh
├── ami-eks-node/
│ ├── template.pkr.hcl
│ └── variables.pkr.hcl
└── docker-base/
└── template.pkr.hcl
Each Packer component contains HCL templates that use variables passed from Atmos:
```hcl variable "region" { type = string description = "AWS region to build the AMI" }variable "instance_type" { type = string default = "t3.medium" description = "EC2 instance type for the builder" }
variable "source_ami_filter" { type = object({ name = string owner = string }) description = "Filter for source AMI" }
variable "ami_name_prefix" { type = string description = "Prefix for the AMI name" }
variable "tags" { type = map(string) default = {} description = "Tags to apply to the AMI" }
</File>
<File title="components/packer/ami-ubuntu/template.pkr.hcl">
```hcl
packer {
required_plugins {
amazon = {
version = ">= 1.2.0"
source = "github.com/hashicorp/amazon"
}
}
}
source "amazon-ebs" "ubuntu" {
region = var.region
instance_type = var.instance_type
source_ami_filter {
filters = {
name = var.source_ami_filter.name
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = [var.source_ami_filter.owner]
}
ami_name = "${var.ami_name_prefix}-ubuntu-{{timestamp}}"
tags = merge(var.tags, {
Name = "${var.ami_name_prefix}-ubuntu"
BuildTime = timestamp()
})
ssh_username = "ubuntu"
}
build {
sources = ["source.amazon-ebs.ubuntu"]
provisioner "shell" {
scripts = [
"${path.root}/scripts/setup.sh",
"${path.root}/scripts/cleanup.sh"
]
}
}
Define defaults for all Packer components:
# Apply to all Packer components
packer:
vars:
region: us-east-1
tags:
ManagedBy: Atmos
Builder: Packer
env:
PACKER_LOG: "1"
AWS_PROFILE: acme-build
# Individual components
components:
packer:
ami-ubuntu:
vars:
instance_type: t3.mediumvars: region: us-east-1 stage: prod
packer: vars: tags: Environment: prod ManagedBy: Atmos env: AWS_PROFILE: acme-prod
components: packer: ami-ubuntu-base: metadata: component: ami-ubuntu vars: instance_type: t3.medium ami_name_prefix: "acme-prod" source_ami_filter: name: "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*" owner: "099720109477"
ami-eks-node:
metadata:
component: ami-eks-node
vars:
instance_type: t3.large
ami_name_prefix: "acme-prod-eks"
kubernetes_version: "1.28"
source_ami_filter:
name: "amazon-eks-node-1.28-*"
owner: "602401143452" # Amazon EKS
settings:
depends_on:
- component: ami-ubuntu-base
type: packer
docker-base:
metadata:
component: docker-base
vars:
repository: "acme/base"
tag: "{{ .stage }}-{{ timestamp }}"
base_image: "ubuntu:22.04"
</File>
## Running Packer Commands
Atmos provides commands that wrap Packer operations:
```bash
# Initialize Packer plugins
atmos packer init ami-ubuntu -s plat-ue1-prod
# Validate templates
atmos packer validate ami-ubuntu -s plat-ue1-prod
# Build images
atmos packer build ami-ubuntu -s plat-ue1-prod
# Run any packer subcommand
atmos packer <subcommand> <component> -s <stack>
Common environment variables for Packer components:
- `PACKER_LOG`
- Enable logging (set to `1`).
- `PACKER_LOG_PATH`
- Path to log file.
- `AWS_PROFILE`
- AWS profile for authentication.
- `AWS_REGION`
- Default AWS region.
- `PACKER_CACHE_DIR`
- Directory for Packer cache.
Atmos generates a variables file that Packer uses during builds:
// atmos-packer.pkrvars.json (auto-generated)
{
"region": "us-east-1",
"instance_type": "t3.medium",
"ami_name_prefix": "acme-prod",
"source_ami_filter": {
"name": "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*",
"owner": "099720109477"
},
"tags": {
"Environment": "prod",
"ManagedBy": "Atmos"
}
}Packer components can build images for multiple cloud providers:
components:
packer:
ami-builder:
vars:
region: us-east-1
source_ami_filter:
name: "ubuntu/images/*"
owner: "099720109477"components:
packer:
azure-image:
vars:
azure_subscription_id: "{{ env \"ARM_SUBSCRIPTION_ID\" }}"
azure_resource_group: "packer-images-rg"
azure_location: "eastus"
env:
ARM_CLIENT_ID: "{{ env \"ARM_CLIENT_ID\" }}"
ARM_CLIENT_SECRET: "{{ env \"ARM_CLIENT_SECRET\" }}"components:
packer:
gcp-image:
vars:
project_id: "my-gcp-project"
zone: "us-central1-a"
source_image_family: "ubuntu-2204-lts"
env:
GOOGLE_APPLICATION_CREDENTIALS: "/path/to/credentials.json"components:
packer:
docker-image:
vars:
repository: "myregistry/myimage"
tag: "latest"
base_image: "ubuntu:22.04"
env:
DOCKER_HOST: "unix:///var/run/docker.sock"-
Version Pin Plugins: Always specify explicit plugin versions in your Packer templates.
-
Use Source AMI Filters: Use filters with
most_recent = trueto automatically get the latest base images. -
Tag Everything: Apply consistent tags to all built images for tracking and cost allocation.
-
Use Provisioner Scripts: Keep provisioning logic in external scripts for easier testing and maintenance.
-
Clean Up: Include cleanup scripts to reduce image size and remove sensitive data.
-
Use Dependencies: Define
depends_onwhen images need to be built in a specific order. -
Centralize Defaults: Define common settings in catalog defaults and override only when necessary.