Use Ansible and Packer to create a Docker image

To create a Docker image, you usually use Docker CLI with the docker build command. One of the advantages is that this command creates one layer per line of the Dockerfile.
However, when you create several Docker images with common code, it may be appropriate to use the Ansible role concept.

Install Packer on MacOS

Install the repository of the packages Homebrew, tap:

brew tap hashicorp/tap
==> Tapping hashicorp/tap
Cloning into '/usr/local/Homebrew/Library/Taps/hashicorp/homebrew-tap'...
remote: Enumerating objects: 123, done.
remote: Counting objects: 100% (123/123), done.
remote: Compressing objects: 100% (99/99), done.
remote: Total 532 (delta 54), reused 70 (delta 24), pack-reused 409
Receiving objects: 100% (532/532), 107.08 KiB | 275.00 KiB/s, done.
Resolving deltas: 100% (221/221), done.
Tapped 6 formulae (42 files, 181.9KB).
brew install hashicorp/tap/packer
==> Installing packer from hashicorp/tap
==> Downloading https://releases.hashicorp.com/packer/1.6.4/packer_1.6.4_darwin_amd64.zip
######################################################################## 100.0%
packer --version
🍺 /usr/local/Cellar/packer/1.6.4: 3 files, 140.9MB, built in 8 seconds
packer --version
1.6.4

Create the configuration file of Packer

Let’s create the configuration file of Packer, ubuntu.json, with this content:

{
"builders": [
{
"name": "docker",
"type": "docker",
"image": "ubuntu:16.04",
"commit": true
}
],
"provisioners": [
{
"type": "shell",
"script": "install_python.sh"
},
{
"type": "ansible",
"playbook_file": "playbook.yaml"
}
],
"post-processors": [
{
"type": "docker-tag",
"repository": "my-image",
"tag": "1.0"
}
]
}
#!/bin/bashapt-get update
apt install -y python
--- 
- hosts: all
tasks:
- name: message
debug: msg="Container {{ inventory_hostname }}"
- name: install
package: name=git state=latest
docker: output will be in this color.==> docker: Creating a temporary directory for sharing data...
==> docker: Pulling Docker image: ubuntu:16.04
docker: 16.04: Pulling from library/ubuntu
docker: Digest: sha256:185fec2d6dbe9165f35e4a1136b4cf09363b328d4f850695393ca191aa1475fd
docker: Status: Image is up to date for ubuntu:16.04
docker: docker.io/library/ubuntu:16.04
==> docker: Starting docker container...
...
==> docker: Committing the container
docker: Image ID: sha256:d43b3a7f77a427879b44f6d86720a63c5dbf5834175fa2a2b6ea628f87c14d33
==> docker: Killing the container: 1fdf6787d2cb456ccd9cb3c5d8ae65383bce83bff7c27861af24ed766bcdf882
==> docker: Running post-processor: docker-tag
==> docker (docker-tag): Deprecation warning: "tag" option has been replaced with "tags". In future versions of Packer, this configuration may not work. Please call `packer fix` on your template to update.
docker (docker-tag): Tagging image: sha256:d43b3a7f77a427879b44f6d86720a63c5dbf5834175fa2a2b6ea628f87c14d33
docker (docker-tag): Repository: my-image:1.0
Build 'docker' finished after 1 minute 23 seconds.
==> Wait completed after 1 minute 23 seconds==> Builds finished. The artifacts of successful builds are:
--> docker: Imported Docker image: sha256:d43b3a7f77a427879b44f6d86720a63c5dbf5834175fa2a2b6ea628f87c14d33
--> docker:
docker run -it ubuntu:16.04 sh -c "git"
sh: 1: git: not found
docker run -it my-image:1.0 -c "git --version"
git version 2.7.4

The new way to create Packer configuration file

A new way to create configuration files is to use HCL. HCL is already used for example by Terraform.
These files must have the extension .pkr.hcl. Here is the equivalent of our ubuntu.json file in HCL :

variable "tag" {
type = string
}
source "docker" "ubuntu" {
commit = true
image = "ubuntu:16.04"
}
build {
sources = ["source.docker.ubuntu"]
provisioner "shell" {
script = "install_python.sh"
}
provisioner "ansible" {
playbook_file = "playbook.yaml"
}
post-processor "docker-tag" {
repository = "my-image"
tag = [ var.tag ]
}
}
mv ubuntu.json.pkr.hcl ubuntu.pkr.hcl

Interests in the full lifecycle: design, Agile Coaching, development, testing, DevOps, Cloud, Management 3.0, ITIL. It defines me.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store