Introduction to Packer by creating an AMI (Amazon Machine Images)
Tags: aws, ami, packer, devops
Published: 2018-05-19 15:28:41

---
title: Introduction to Packer by creating an AMI (Amazon Machine Images)
published: true
description: Creating AWS Centos 7 AMI with Nginx Preinstalled using Hashicorp Packer.
tags: AWS,AMI,Packer,Devops
---

# What is Packer ?
A tool from Hashicorp to build machine images for most platforms (AWS,Google Cloud,Digital Ocean,Docker,Azure to name a few) and automate configurations and installation of softwares that need to be present.

We define how to build the image in a JSON template file.This should be version controlled and is treated like any other code.

> [Infrastructure As Code.](http://infrastructure-as-code.com/)

# Sections of Packer template
<br/>

## Builders
A builder takes care of creating an image.Packer provides builders for various platforms.
For this example we will be using **amazon-ebs** as builder.
We provide platform specific configurations in the builder section of the template.Like what type of instance (t2-micro m4-large etc) to spin up to create the image, SSH/Access details or credentials. You can create custom builders as well though we wont be covering this. 

Builders use Communicators to establish connection with the created instance. Either it can be a SSH connection or WINRM for Windows machine.

## Provisioners 
Once a machine is created by the builder we will use provisioners to install softwares and configure the machine to a desired state.Packer provide provisioners for configuration management tools like Chef/Puppet/Ansible or good old shell script.

## Post-Processors

Once the machine is created and softwares installed and configurations applied by Provisioners Post-Processors are run. We can use them for example to push a docker image to a registry. We wont be covering this and for details [please refer this documentation.](https://www.packer.io/docs/post-processors/index.html)

## Variables
Packer template should be made generic so it can be used in different environment and keeping secrets/credentials secure by not providing them in the template file. Use user variables in place of such configurations.

In the template below we use user variables for *name, sourceami, accesskey, secretkey, region*. For some of these we have provided a default  value in the variable sections other are left as empty,We can pass in the value while building the image using **-var** parameter.

## So What exactly does Packer do ?
* Packer will spin up an instance for the specified platform based on the type of builder.
* Use the Communicator specified to connect to the machine.
* Run all the provisioners to configure and install softwares. 
* It the runs any post-processors specified in the JSON template.
* Finally it terminates machines and any temporary resources it created in the process, eg: security group, temporary ssh key-pair etc.

# Getting hands dirty with Packer
<br/>

## What are we going to do ?
<br/>

* Create an AMI with Nginx pre-installed
    * Choose source_ami as CentOS 7
    * Install EPEL (Extra packages for enterprise Linux)
    * Install nginx
    * Enable nginx to start on boot

```
{
    "variables": {
      "name": "centos_7_nginx",
      "source_ami": "ami-d5bf2caa",
      "access_key":"",
      "secret_key":"",
      "region":"us-east-1"
    },
    "builders": [{
      "type": "amazon-ebs",
      "access_key": "{{user `access_key`}}",
      "secret_key":"{{user `secret_key`}}",
      "ami_name": "{{user `name`}}",
      "region": "{{user `region`}}",
      "source_ami": "{{user `source_ami`}}",
      "instance_type": "t2.micro",
      "communicator": "ssh",
      "ssh_username": "centos",
      "run_tags":{"Name":"packer-image"}
    }],
    "provisioners": [
        {
            "type": "shell",
            "inline": "sudo yum install -y epel-release"
        },
        {
            "type": "shell",
            "inline": ["sudo yum install -y nginx","sudo systemctl enable nginx", "sudo systemctl start nginx"]
        }
      ]
  }
```

##Command to build image :
``` 
packer build -var 'access_key=XXXXXXXXXXX' -var 'secret_key=XXXXXXXXXXXXXXXXXXXXXXXX' aws_centos_nginx.json 
```

Before running the above command you can validate the file using `packer validate template.json`
## Note:
* Generate a secret key and access key from AWS which have authorization for creating image and pass the packer build command.
* The source AMI specified above is CentOS Linux 7 x86_64 HVM EBS.
* Communicator used is SSH and we specify the default username which is centos.
* AMI are region specific so ensure you select us-east-1 or N.Virginia as your current region.
* run_tags are tags assigned to the machine used to create the image.This machine will be terminated once the image is created.
* We have used shell prvisioner in the above example with inline mode. First with just a single command then with an array of commands to run.

> Originally posted in [JigsawCode](https://www.jigsawcode.com)

## Where to next ?
[Packer Recipes to bake an EC2 AMI](https://www.jigsawcode.com/packer-recipes-for-ec2-ami/)

##References:
[Packer Documentation](https://www.packer.io/docs/index.html)

P.S If you find it useful,I will write a second part exploring more features of Packer.