Provision
In the previous tutorial, you created your first container image with Packer. However, the image you built essentially repackaged an existing Docker image. The real utility of Packer comes from automated provisioning in order to install and configure software in the machines prior to turning them into images.
Historically, pre-baked images have been frowned upon because changing them was so tedious and slow. Because Packer is completely automated (including provisioning) images can be changed quickly and integrated with modern configuration management tools such as Chef or Puppet.
In this tutorial, you will use provisioners to set an environment variable and create a file in your Docker image. Although defining environment variables and creating a file in a Docker image is a small example, it should give you an idea of what Packer provisioners can do.
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
.Initialize the Packer template.
Once you have successfully initialized the template, you can continue with the rest of this tutorial.
Add provisioner to template
Using provisioners allows you to completely automate modifications to your image. You can use shell scripts, file uploads, and integrations with modern configuration management tools such as Chef or Puppet.
To write your first provisioner, add the following block into your Packer template, inside the build block and underneath the sources
assignment.
This block defines a shell
provisioner which sets an environment variable named FOO
in the shell execution environment and runs the commands in the inline
attribute. This provisioner will create a file named example.txt
that contains FOO is hello world
.
Your build block should look like the following.
Build image
Build the image with the provisioner.
In the output, you will find the Provisioning with shell script
that confirms that the Packer ran the provision step. Notice how Packer also outputs the first inline command (Adding file to Docker Container
).
Verify update image
Verify the image by running it with Docker. You'll need the IMAGE_ID
from the output of docker images
.
To verify the provisioner created the example.txt
file in the new image, first launch the newly created Docker image. Replace IMAGE_ID
with the value shown above in your terminal (your local equivalent of 6e5eeb4
as shown in the output above).
In the Docker container shell, print the contents of the example.txt
file. This should return FOO is hello world
as expected.
Type exit
to leave the container.
Add more provisioners
The shell provisioner demonstrated above is extremely powerful and flexible. For complex provisioning, you can pass entire shell scripts rather than the inline
declarations shown above.
You can run as many provisioners as you'd like. Provisioners run in the order they are declared.
Replace your existing build block with the following. This adds a provisioner to the end of your build block that will print a message in the shell execution environment.
Build and verify updated image
Build the image again.
Notice how there are two Provisioning with shell-script
executions. The second provisioning step displays the expected message.
Next steps
In this tutorial, you used provisioners to set an environment variable and create a file in your Docker image. You can apply these same principles to provisioning and configuring any Packer images. Continue to the next tutorial to make your Packer template more robust with variables.
Refer to the following resources for additional details on the concepts covered in this tutorial:
- Read more about the Packer provisioners.
- Learn more about how to use Packer provisioner blocks.