Packer, Ansible and Docker Part 2: Using Ansible Galaxy
Previously we setup packer, docker and ansible to build a very simple docker image that simply placed a file under /root
with some content, a very simple start. Today we’ll go further and explore using ansible roles and making some pieces a bit more dynamic.
A Real World Example
In this tutorial, we’ll build a docker image that has Redis installed. While we could go through the steps of adding an apt repository, installing and configuring Redis ourselves why not go strong and take advantage of the fact that someone else has already done this? Enter ansible-galaxy
.
Using Ansible Galaxy
Simply put, ansible galaxy is pretty much like any package manager for your favorite language like pip for python or npm for node. You can install packages stand-alone by running something like ansible-galaxy install geerlinguy.redis
or you can define a requirements file just like in python to specify multiple dependencies.
Finding the Right Role
If we do a search we’ll soon discover that there are 150 or so odd redis roles out there… which do we use? Usually we’ll want to temper our choice to the one with the most downloads. A very quick method I use is to just google ansible-galaxy <service>
and run with the first result. Thankfully the search for ansible-galaxy redis
returns geerlingguy.redis
which is by a guy I know puts out some pretty high quality roles. But if I didn’t know that, the number of downloads are a good indicator!
Adding our Requirements File
Our requirements.yml
file is off to a simple start.
--- - src: geerlingguy.redis version: 1.1.5
While the ansible-local
provisioner lets you define a galaxy_file
and installs roles for you the ansible-remote
provisioner (which we’re using) does not. So we’ll need to install the roles and specify the directory in they’ll be installed in. While roles
is typically a good directory name I prefer to store my galaxy related roles in a separate directory and leave roles
for my own roles (which we’ll cover in a later blog post). For today, let’s use galaxy
for roles installed from ansible-galaxy. You can specify the target path with the -p
option below.
$ ansible-galaxy install -p galaxy -r requirements.yml
This is also a good time to update our playbook to use the role.
--- - name: A demo to run ansible in a docker container hosts: all tasks: - name: Add a file to root's home dir copy: dest: /root/foo content: Hello World! owner: root roles: - geerlingguy.redis
Finally, we need to tell ansible where our role directories are. We can do this by defining the ANSIBLE_ROLES_PATH
environment variable. So we update our template.json
to the below content with that added.
{ "variables": { "ansible_host": "default", "ansible_connection": "docker", "ansible_roles_path": "galaxy" }, "builders": [{ "type": "docker", "image": "ubuntu:16.04", "commit": "true", "run_command": [ "-d", "-i", "-t", "--name", "{{user `ansible_host`}}", "{{.Image}}", "/bin/bash" ] }], "provisioners": [ { "type": "shell", "inline": [ "apt-get update", "apt-get install python -yq" ] }, { "type": "ansible", "ansible_env_vars": [ "ANSIBLE_ROLES_PATH={{user `ansible_roles_path` }}" ], "user": "root", "playbook_file": "./playbook.yml", "extra_arguments": [ "--extra-vars", "ansible_host={{user `ansible_host`}} ansible_connection={{user `ansible_connection`}}" ] } ], "post-processors": [ [ { "type": "docker-tag", "repository": "jamescarr/demo", "tag": "0.1" } ] ] }
With all of these changes made, let’s run packer again.
$ packer build template.json
If all goes well, we’ll see the tasks to install redis get executed.
And if we run our container we can see redis is indeed installed!
$ docker run -it jamescarr/demo:0.1 bash
For reference, you can see the project in its entirety at https://github.com/jamescarr/pad-tutorial/tree/part-two.
This is pretty nifty stuff… no more Dockerfiles
masquerading as glorified bash scripts. How about we take this further and use the same docker template to build out multiple different types of docker images?
Next Up
Tomorrow I’ll write up part three and we’ll explore making this template more dynamic and utilize our own roles to layout specific tasks.
Reference: | Packer, Ansible and Docker Part 2: Using Ansible Galaxy from our WCG partner James Carr at the James Carr blog. |