Packer - tutorial

Page content

Install

https://learn.hashicorp.com/tutorials/packer/get-started-install-cli

I installed pre-compiled version from the official download page (just download a binary).

cd /usr/local/src
sudo curl https://releases.hashicorp.com/packer/1.7.6/packer_1.7.6_linux_amd64.zip -O
sudo unzip packer_1.7.6_linux_amd64.zip
sudo mv packer /usr/bin/
packer version

Use

Build a Docker image

mkdir packer_tutorial
cd packer_tutorial
touch docker-ubuntu.pkr.hcl

In the file docker-ubuntu.pkr.hcl, we define how to set up Pakcer environment and how to build artifacts (images/containers/VMs/etc.).

docker-ubuntu.pkr.hcl:

packer {
  required_plugins {
    docker = {
      version = ">= 0.0.7"
      source = "github.com/hashicorp/docker"
    }
  }
}

source "docker" "ubuntu" {
  image  = "ubuntu:xenial"
  commit = true
}

build {
  name    = "learn-packer"
  sources = [
    "source.docker.ubuntu"
  ]
}

Sections

  • pakcer: define Packer environment
  • source: specify “builder” and it’s name
  • build: actual build scripts

Let’s build the docker image using Pakcer:

$ packer init .
Installed plugin github.com/hashicorp/docker v1.0.1 in "/home/atlex00/.config/packer/plugins/github.com/hashicorp/docker/packer-plugin-docker_v1.0.1_x5.0_linux_amd64"
$ packer validate .
$ packer build docker-ubuntu.pkr.hcl
learn-packer.docker.ubuntu: output will be in this color.

==> learn-packer.docker.ubuntu: Creating a temporary directory for sharing data...
==> learn-packer.docker.ubuntu: Pulling Docker image: ubuntu:xenial
    learn-packer.docker.ubuntu: xenial: Pulling from library/ubuntu
    learn-packer.docker.ubuntu: 58690f9b18fc: Pulling fs layer
    learn-packer.docker.ubuntu: b51569e7c507: Pulling fs layer
    learn-packer.docker.ubuntu: da8ef40b9eca: Pulling fs layer
    learn-packer.docker.ubuntu: fb15d46c38dc: Pulling fs layer
    learn-packer.docker.ubuntu: fb15d46c38dc: Waiting
    learn-packer.docker.ubuntu: b51569e7c507: Verifying Checksum
    learn-packer.docker.ubuntu: b51569e7c507: Download complete
    learn-packer.docker.ubuntu: da8ef40b9eca: Verifying Checksum
    learn-packer.docker.ubuntu: da8ef40b9eca: Download complete
    learn-packer.docker.ubuntu: 58690f9b18fc: Verifying Checksum
    learn-packer.docker.ubuntu: 58690f9b18fc: Download complete
    learn-packer.docker.ubuntu: fb15d46c38dc: Verifying Checksum
    learn-packer.docker.ubuntu: fb15d46c38dc: Download complete
    learn-packer.docker.ubuntu: 58690f9b18fc: Pull complete
    learn-packer.docker.ubuntu: b51569e7c507: Pull complete
    learn-packer.docker.ubuntu: da8ef40b9eca: Pull complete
    learn-packer.docker.ubuntu: fb15d46c38dc: Pull complete
    learn-packer.docker.ubuntu: Digest: sha256:454054f5bbd571b088db25b662099c6c7b3f0cb78536a2077d54adc48f00cd68
    learn-packer.docker.ubuntu: Status: Downloaded newer image for ubuntu:xenial
    learn-packer.docker.ubuntu: docker.io/library/ubuntu:xenial
==> learn-packer.docker.ubuntu: Starting docker container...
    learn-packer.docker.ubuntu: Run command: docker run -v /home/atlex00/.packer.d/tmp223497265:/packer-files -d -i -t --entrypoint=/bin/sh -- ubuntu:xenial
    learn-packer.docker.ubuntu: Container ID: a5fe1f0a59a20ed90cbbcb6d75569d5861fa7c76a74e639e1a62c618a3aca3cf
==> learn-packer.docker.ubuntu: Using docker communicator to connect: 172.17.0.2
==> learn-packer.docker.ubuntu: Committing the container
    learn-packer.docker.ubuntu: Image ID: sha256:33ff70ba518666521f7f3d831497b58491bc38a6911d442eff49ed2886de669f
==> learn-packer.docker.ubuntu: Killing the container: a5fe1f0a59a20ed90cbbcb6d75569d5861fa7c76a74e639e1a62c618a3aca3cf
Build 'learn-packer.docker.ubuntu' finished after 5 seconds 14 milliseconds.

==> Wait completed after 5 seconds 14 milliseconds

==> Builds finished. The artifacts of successful builds are:
--> learn-packer.docker.ubuntu: Imported Docker image: sha256:33ff70ba518666521f7f3d831497b58491bc38a6911d442eff49ed2886de669f

The you can check the built image:

$ docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
<none>       <none>    33ff70ba5186   7 seconds ago   135MB

Customize the Docker image

Letzs change the build section:

packer {
  required_plugins {
    docker = {
      version = ">= 0.0.7"
      source = "github.com/hashicorp/docker"
    }
  }
}

source "docker" "ubuntu" {
  image  = "ubuntu:xenial"
  commit = true
}

build {
  name    = "learn-packer"
  sources = [
    "source.docker.ubuntu"
  ]
  provisioner "shell" {
    environment_vars = [
      "FOO=hello world",
    ]
    inline = [
      "echo Adding file to Docker Container",
      "echo \"FOO is $FOO\" > example.txt",
    ]
  }
}

The pre-defined provisioner shell execute the shell scripts after Packer runs a temporary Docker container, and it commit the changes (update the image).

You can run and check the created image (in my case, the image ID starts with 810a778cc7ba).

docker run -it 810a778cc7ba
# pwd
/
# ls  		
bin  boot  dev	etc  example.txt  home	lib  lib64  media  mnt	opt  packer-files  proc  root  run  sbin  srv  sys  tmp  usr  var
# cat example.txt
FOO is hello world

Customize more

Add provisioner section in build sections.

packer {
  required_plugins {
    docker = {
      version = ">= 0.0.7"
      source = "github.com/hashicorp/docker"
    }
  }
}

source "docker" "ubuntu" {
  image  = "ubuntu:xenial"
  commit = true
}

build {
  name    = "learn-packer"
  sources = [
    "source.docker.ubuntu"
  ]

  provisioner "shell" {
    environment_vars = [
      "FOO=hello world",
    ]
    inline = [
      "echo Adding file to Docker Container",
      "echo \"FOO is $FOO\" > example.txt",
    ]
  }

  provisioner "shell" {
    inline = ["echo This provisioner runs last"]
  }
}

When you build the image again, you can see the message This provisioner runs last, which is echoed inside the container during the build process.

$ packer build docker-ubuntu.pkr.hcl 
learn-packer.docker.ubuntu: output will be in this color.

==> learn-packer.docker.ubuntu: Creating a temporary directory for sharing data...
==> learn-packer.docker.ubuntu: Pulling Docker image: ubuntu:xenial
    learn-packer.docker.ubuntu: xenial: Pulling from library/ubuntu
    learn-packer.docker.ubuntu: Digest: sha256:454054f5bbd571b088db25b662099c6c7b3f0cb78536a2077d54adc48f00cd68
    learn-packer.docker.ubuntu: Status: Image is up to date for ubuntu:xenial
    learn-packer.docker.ubuntu: docker.io/library/ubuntu:xenial
==> learn-packer.docker.ubuntu: Starting docker container...
    learn-packer.docker.ubuntu: Run command: docker run -v /home/atelx00/.packer.d/tmp989129153:/packer-files -d -i -t --entrypoint=/bin/sh -- ubuntu:xenial
    learn-packer.docker.ubuntu: Container ID: 9c1fc58331acd0e14328cdab4bcb5c77638697c1ec071ceff0aa75770e24ff8c
==> learn-packer.docker.ubuntu: Using docker communicator to connect: 172.17.0.2
==> learn-packer.docker.ubuntu: Provisioning with shell script: /tmp/packer-shell3185205585
    learn-packer.docker.ubuntu: Adding file to Docker Container
==> learn-packer.docker.ubuntu: Provisioning with shell script: /tmp/packer-shell1463249716
    learn-packer.docker.ubuntu: This provisioner runs last
==> learn-packer.docker.ubuntu: Committing the container
    learn-packer.docker.ubuntu: Image ID: sha256:d3f882ee83ee175580204968ce93cb3c605ae9eb6f1a784ec7251de3ea7af9c4
==> learn-packer.docker.ubuntu: Killing the container: 9c1fc58331acd0e14328cdab4bcb5c77638697c1ec071ceff0aa75770e24ff8c
Build 'learn-packer.docker.ubuntu' finished after 2 seconds 888 milliseconds.