Packer AMI tags are the unsung heroes of automated AWS image building, allowing you to imbue your AMIs with the metadata necessary for seamless integration into your infrastructure.
Let’s see Packer in action, tagging an AMI during the build process. Imagine you have a packer.json file like this:
{
"builders": [
{
"type": "amazon-ebs",
"region": "us-east-1",
"source_ami": "ami-0c55b159cbfafe1f0", // Example: Ubuntu 20.04 LTS
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "my-app-{{timestamp}}",
"tags": {
"Name": "my-app-base-image",
"Environment": "staging",
"Version": "1.2.0",
"CreatedBy": "Packer"
}
}
],
"provisioners": []
}
When Packer runs packer build packer.json, it will not only create an AMI but also attach the specified tags to it. You can then verify this in the AWS EC2 console under the "Tags" tab for the newly created AMI.
The core problem Packer AMI tags solve is discoverability and automation. Without them, identifying the correct AMI for a specific environment, application version, or purpose becomes a manual, error-prone process. Imagine having dozens or hundreds of AMIs; how do you programmatically find the latest "production-ready" Ubuntu 20.04 image for your web servers? Tags provide that structured metadata.
Internally, Packer interacts with the AWS EC2 API. When the amazon-ebs builder finishes creating an AMI, Packer makes a subsequent API call to CreateTags (or Tagging operations) for the newly generated AMI ID, applying the key-value pairs defined in your tags block. This is a two-step process: first, the AMI is created; second, the tags are applied.
The exact levers you control are within the tags block of your builder configuration. You can add any arbitrary key-value pairs. Common and highly recommended tags include:
Name: A human-readable identifier for the AMI.Environment: (e.g.,development,staging,production) to differentiate images intended for different deployment stages.Version: A specific application or image version number.CreatedBy: Often set toPackerto easily identify machine-generated images.Owner: The team or individual responsible for the image.Project: The project name the AMI belongs to.
You can also leverage environment variables or Packer’s templating features to make your tags dynamic. For instance, to automatically include the Git commit hash of your application code in the AMI tags, you could do something like this:
{
"variables": {
"git_commit": ""
},
"builders": [
{
"type": "amazon-ebs",
// ... other builder config ...
"tags": {
"Name": "my-app-{{timestamp}}",
"Environment": "{{env `CI_ENVIRONMENT`}}", // Example: Using a CI environment variable
"GitCommit": "{{user `git_commit`}}", // Example: Using a variable passed on the command line
"CreatedBy": "Packer"
}
}
]
}
Then, you’d run Packer like so: PACKER_VAR_dir=./vars packer build -var 'git_commit=abcdef123' -var 'CI_ENVIRONMENT=production' my-packer-config.json.
The one thing most people don’t realize is that the Name tag is not the same as the ami_name configuration parameter. ami_name is the unique identifier for the AMI at the time of creation and often includes timestamps or build numbers to ensure uniqueness. The Name tag, however, is a descriptive label that can be the same across multiple AMI versions if they serve the same core purpose (e.g., "Ubuntu 20.04 LTS - Web Server Base"). AWS console searches and filtering often prioritize tags, making the Name tag crucial for quick identification.
Once you’ve mastered tagging, the next logical step is to use these tags to automate AMI selection in your deployment pipelines, perhaps using tools like AWS Systems Manager Parameter Store to store the latest AMI ID based on specific tags.