Packer
Post-processors
In the last tutorial, you updated your template to build multiple images in parallel.
While provisioners are run against an instance while it is running, post-processors run only after Packer saves the instance as an image. Post-processors are extremely varied in their function; they can compress your artifact, upload your artifact into a cloud, or create a file that describes the artifact and build.
In this tutorial, you will add the docker-tag post-processor to add a tag to the Docker image.
Prerequisites
This tutorial assumes that you are continuing from the previous tutorials. If not, follow the steps below before continuing.
Install Packer
Create a directory named
packer_tutorial
and paste the following configuration into a file nameddocker-ubuntu.pkr.hcl
.packer { required_plugins { docker = { version = ">= 1.0.8" source = "github.com/hashicorp/docker" } } } variable "docker_image" { type = string default = "ubuntu:jammy" } source "docker" "ubuntu" { image = var.docker_image commit = true } source "docker" "ubuntu-focal" { image = "ubuntu:focal" commit = true } build { name = "learn-packer" sources = [ "source.docker.ubuntu", "source.docker.ubuntu-focal", ] provisioner "shell" { environment_vars = [ "FOO=hello world", ] inline = [ "echo Adding file to Docker Container", "echo \"FOO is $FOO\" > example.txt", ] } provisioner "shell" { inline = ["echo Running ${var.docker_image} Docker image."] } }
Initialize the Packer template.
$ packer init .
Once you have successfully initialized the template, you can continue with the rest of this tutorial.
Add post-processor to template
Add the following post-processor blocks inside the build block but after the provisioner step. These post-processor blocks will tag each image with the appropriate tags.
post-processor "docker-tag" {
repository = "learn-packer"
tags = ["ubuntu-jammy", "packer-rocks"]
only = ["docker.ubuntu"]
}
post-processor "docker-tag" {
repository = "learn-packer"
tags = ["ubuntu-focal", "packer-rocks"]
only = ["docker.ubuntu-focal"]
}
Your build block should look like the following.
build {
name = "learn-packer"
sources = [
"source.docker.ubuntu",
"source.docker.ubuntu-focal",
]
provisioner "shell" {
environment_vars = [
"FOO=hello world",
]
inline = [
"echo Adding file to Docker Container",
"echo \"FOO is $FOO\" > example.txt",
]
}
provisioner "shell" {
inline = ["echo Running ${var.docker_image} Docker image."]
}
post-processor "docker-tag" {
repository = "learn-packer"
tags = ["ubuntu-jammy", "packer-rocks"]
only = ["docker.ubuntu"]
}
post-processor "docker-tag" {
repository = "learn-packer"
tags = ["ubuntu-focal", "packer-rocks"]
only = ["docker.ubuntu-focal"]
}
}
Build and tag images
Build the images.
$ packer build .
learn-packer.docker.ubuntu: output will be in this color.
learn-packer.docker.ubuntu-focal: output will be in this color.
==> learn-packer.docker.ubuntu-focal: Creating a temporary directory for sharing data...
==> learn-packer.docker.ubuntu-focal: Pulling Docker image: ubuntu:focal
==> learn-packer.docker.ubuntu: Creating a temporary directory for sharing data...
==> learn-packer.docker.ubuntu: Pulling Docker image: ubuntu:focal
## ...
==> learn-packer.docker.ubuntu: Running post-processor: (type docker-tag)
docker.ubuntu (docker-tag): Tagging image: sha256:2d0b6deb04c736d3928a99a1a4c74df5144ddfc52b6756139ed143c3b1fea6ae
docker.ubuntu (docker-tag): Repository: learn-packer:ubuntu-jammy
==> learn-packer.docker.ubuntu-focal: Running post-processor: (type docker-tag)
docker.ubuntu-focal (docker-tag): Tagging image: sha256:c53211544dce810160d545587a92ed952802a536a2a55d7abe3946186f0944c4
docker.ubuntu-focal (docker-tag): Repository: learn-packer:ubuntu-focal
docker.ubuntu (docker-tag): Tagging image: sha256:2d0b6deb04c736d3928a99a1a4c74df5144ddfc52b6756139ed143c3b1fea6ae
docker.ubuntu (docker-tag): Repository: learn-packer:packer-rocks
docker.ubuntu-focal (docker-tag): Tagging image: sha256:c53211544dce810160d545587a92ed952802a536a2a55d7abe3946186f0944c4
docker.ubuntu-focal (docker-tag): Repository: learn-packer:packer-rocks
Build 'learn-packer.docker.ubuntu' finished after 15 seconds 693 milliseconds.
Build 'learn-packer.docker.ubuntu-focal' finished after 15 seconds 837 milliseconds.
==> Wait completed after 15 seconds 837 milliseconds
==> Builds finished. The artifacts of successful builds are:
--> learn-packer.docker.ubuntu: Imported Docker image: sha256:2d0b6deb04c736d3928a99a1a4c74df5144ddfc52b6756139ed143c3b1fea6ae
--> learn-packer.docker.ubuntu: Imported Docker image: learn-packer:packer-rocks with tags learn-packer:ubuntu-jammy learn-packer:packer-rocks
--> learn-packer.docker.ubuntu-focal: Imported Docker image: sha256:c53211544dce810160d545587a92ed952802a536a2a55d7abe3946186f0944c4
--> learn-packer.docker.ubuntu-focal: Imported Docker image: learn-packer:packer-rocks with tags learn-packer:ubuntu-focal learn-packer:packer-rocks
List the images to verify Packer successfully tagged each image.
$ docker images learn-packer
REPOSITORY TAG IMAGE ID CREATED SIZE
learn-packer packer-rocks c53211544dce 23 seconds ago 63.1MB
learn-packer ubuntu-focal c53211544dce 23 seconds ago 63.1MB
learn-packer ubuntu-jammy 2d0b6deb04c7 24 seconds ago 63.1MB
Notice how there are only three images. This is because the ubuntu-focal
post-processing step overrides the image created by ubuntu-jammy
. You can verify this by reading through the Packer build logs.
Sequential post-processing steps
You may add as many post-processors as you want using the post-processor
syntax, but each one will start from the original artifact output by the builder, not the
artifact created by a previously declared post-processor.
Use the post-processors
(note the pluralization) block to create post-processing pipelines where the output of one post-processor becomes the input to another post-processor.
For example, the following configuration will tag your image then push it to Docker Hub. You do not need to add this to your configuration for this tutorial, since it requires a Docker account and will push your image to Docker Hub.
post-processors {
post-processor "docker-import" {
repository = "swampdragons/testpush"
tag = "0.7"
}
post-processor "docker-push" {}
}
You can add as many post-processors blocks as you want, or mix-and-match the one-off post-processors with the post-processors
blocks to create multiple pathways for post-processing.
Next steps
In this tutorial, you added post-processors to your Packer template to tag Docker images.
This is the end of the getting started tutorials for Packer. You should now be comfortable with basic Packer usage, should understand templates, defining builds, provisioners, post-processors, and more. At this point, you are ready to begin playing with and using Packer in real scenarios.
If you would like to learn how to use Packer to build Amazon images, check out our Get Started - Amazon tutorials.
The most important reference in your Packer journey will be the documentation. The documentation contains reference material for Packer's features and configuration options.
As you use Packer more, please voice your comments and concerns on the community forum. Additionally, Packer is open source so please contribute if you'd like to. Contributions are very welcome.