Help & Community
Help & Community

Creating Images with Packer

Packer is an open source tool for creating identical machine images for multiple platforms from a single source configuration. Packer is lightweight, runs on every major operating system, and is highly performant, creating machine images for multiple platforms in parallel. Packer does not replace configuration management like Chef or Puppet. In fact, when building images, Packer is able to use tools like Chef or Puppet to install software onto the image. A machine image is a single static unit that contains a pre-configured operating system and installed software which is used to quickly create new running machines.

Advantages of using Packer and images

Super fast infrastructure deployment. Images allows you to launch completely provisioned and configured machines in seconds, rather than several minutes or hours. This benefits not only production, but development as well, since development virtual machines can also be launched in seconds, without waiting for a typically much longer provisioning time.

Multi-provider portability. Because Packer creates identical images for multiple platforms, you can run production in AWS, OpenStack, and development in desktop virtualization solutions such as VMware or VirtualBox. Each environment is running an identical machine image, giving ultimate portability.

Improved stability. Packer installs and configures all the software for a machine at the time the image is built. If there are bugs in these scripts, they'll be caught early, rather than several minutes after a machine is launched.

Greater testability. After a machine image is built, that machine image can be quickly launched and smoke tested to verify that things appear to be working. If they are, you can be confident that any other machines launched from that image will function properly.


Using Packer with Zetta.IO

From version 0.8.x, packer supports Zetta.IO and other modern Openstack clouds with multi-tenant/domain support. We contributed to the Packer project with the first working builder for the platform. The code was used as a base for the new Openstack builder in 0.8.0. Visit the Official Packer page and download the binaries.

To configure Packer you need a JSON template and environment variables with authentication data.

Setting Environment Variables

Let's start with making a simple script that sets the environment variables. This example works for Linux and OS X. You can download an rc file from our dashboard under Overview -> API and modify it for this.

File :

export OS_AUTH_URL=
export OS_DOMAIN_NAME=""
export OS_TENANT_NAME="Standard"
export OS_USERNAME="myusername"
export OS_PASSWORD="mypassword"

Note that the TENANT_NAME is the name of the project you want to create the image in. If you only have one project it would normally be named called "Standard".

JSON Template

File : zetta_test.json

  "builders": [{
      "type": "openstack",
      "image_name": "packer-test-image",
      "source_image": "d0a89aa8-9644-408d-a023-4dcc1148ca01",
      "flavor": "6",
      "floating_ip_pool": "Public",
      "security_groups": ["default"],
      "ssh_username": "ubuntu"
  "provisioners": [{
    "type": "shell",
    "inline": [
      "sleep 30",
      "sudo apt-get update",
      "sudo apt-get install -y nginx"

This template will create an image named "packer-test-image" based on a public Ubuntu 14.04 image and installs Ngix with a simple shell provisioner. The selected flavor is m3.medium (6).

Running Packer

Set the environment variables in the script :

$ source

Run the template :

$ packer build zetta_test.json

The output :

==> openstack: Discovering enabled extensions...
==> openstack: Loading flavor: 6
    openstack: Verified flavor. ID: 6
==> openstack: Creating temporary keypair for this instance...
==> openstack: Launching server...
    openstack: Server ID: 22deb62c-a888-4c76-9523-66816c35cac0
==> openstack: Waiting for server to become ready...
==> openstack: Creating floating IP...
    openstack: Pool: Public
    openstack: Created floating IP: X.X.X.X
==> openstack: Associating floating IP with server...
    openstack: IP: X.X.X.X
    openstack: Added floating IP X.X.X.X to instance!
==> openstack: Waiting for SSH to become available...
==> openstack: Connected to SSH!
==> openstack: Provisioning with shell script: /var/folders/m3/xy78sqz160g_722vt047721r0000gn/T/packer-shell733544044
    openstack: (runs apt-get update)
    openstack: Setting up nginx-core ...
==> openstack: Stopping server...
    openstack: Waiting for server to stop...
==> openstack: Creating the image: packer-test-image
    openstack: Image: 4862f351-511b-4fd7-9ec2-00e605597d57
==> openstack: Waiting for image to become ready...
==> openstack: Deleted temporary floating IP X.X.X.X
==> openstack: Terminating the source server...
==> openstack: Deleting temporary keypair...
Build 'openstack' finished.

You should now be able to find the image in your project. It's ready to launch whenever you need it. This is a fairly basic example just to get started. There are so many ways to run provisioning, and if you're already using provisioning tools, it probably works with packer already. Please see the official documentation for more details. It's also worth stopping by their Github page page.

Additional Notes

The supported environment variables for authentication is :


See : (Packer is using the Gophercloud API for all communication to Openstack)

Builder Steps

It can be practical to know what the Openstack builder does step by step. The goal is to successfully create an image after running provisioners and possibly post-processors. 

Authentication. The user is authenticated and scoped to a project in their domain.

Extension Check. The builder checks what extensions are available.

Flavor Check. Checks if the flavor id for the server actually exists.

Keypair Creation. Creates a temporary keypair for SSH communication.

Launch Server. Starts a server with the supplied image id and flavor with the security groups listed in the template.

Allocate IP. Attempts to release an IP from the pool and set the ower to your project. Then the server is given this public IP. (There are other options for IP allocation as well)

Wait for SSH. Keep trying to ssh to the server. It might not be done booting. This is the most common step to fail initially becuse of too strict security groups or wrong ip pool name. (You could also provision in the local network, so public IPs are structly not needed. Then this step will be skipped)

Run Provisioners. Run whatever provisioner(s) you have configured. The possibilities here are endless. This step will wait until provisioning is completed before it continues.

Stop Server. The server is stopped so we safely create an image.

Create Image. An image creation is queued. We wait for it to complete.

Delete Server. The server is deleted.

Delete Keypair. The temporary keypair is deleted.

Post-Processor. Run post-processors on the final image (optional)

Terms & Conditions
© Zetta.IO Technology 2022