The other day I was asked to convert the shell scripts used to build out our AWS AMI images into ansible playbooks. The issue, we use docker with the hashicorp/packer image, which doesn't have ansible. That set me on this short journey to build a docker image that had the tools we needed, and then some.
For those that just want to jump to the good stuff, here's the links to my Github and Docker Hub repos.
codebarber / ansible-packer-terraform
Docker image with ansible awscli packer and terraform
With docker the image is defined as layers in the build file called Dockerfile. Additional layers are added as needed, and all these layers are steps taken to build your final docker image.
So let's get started writing the dockerfile. In the text editor of your choosing type:
FROM ubuntu:bionic-20200219
This is the first layer instructing docker to pull that docker image as the base layer.
To allow easy version updates lets setup some arguments with defaults set by adding:
ARG TERRAFORM_VERSION="0.12.23"
ARG ANSIBLE_VERSION="2.5.1"
ARG PACKER_VERSION="1.5.4"
ARG AWSCLI_VERSION="1.18.19"
Next we add the metadata for the docker image:
LABEL maintainer="Codebarber <ernest@codebarber.com>"
LABEL terraform_version=${TERRAFORM_VERSION}
LABEL ansible_version=${ANSIBLE_VERSION}
LABEL aws_cli_version=${AWSCLI_VERSION}
You would obviously want to update maintainer if you'll be publishing your own version to Docker Hub. So now we're coming to the next big layer. Here we are installing the packages we want in our image.
Add:
ENV DEBIAN_FRONTEND=noninteractive
ENV AWSCLI_VERSION=${AWSCLI_VERSION}
ENV TERRAFORM_VERSION=${TERRAFORM_VERSION}
ENV PACKER_VERSION=${PACKER_VERSION}
RUN apt-get update \
&& apt-get install -y ansible curl python3 python3-pip python3-boto unzip \
&& pip3 install --upgrade awscli==${AWSCLI_VERSION} \
&& curl -LO https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip \
&& curl -LO https://releases.hashicorp.com/packer/${PACKER_VERSION}/packer_${PACKER_VERSION}_linux_amd64.zip \
&& unzip '*.zip' -d /usr/local/bin \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* *.zip
Above since we are using an ubuntu base image we'll use ubuntu tools and package names. That pretty much completes our image, now we just need to set the command that will be run by this image by setting the CMD as the final step. Here we'll tell our docker image to run bash. This allows us to run multiple tools by passing the command and options to docker run command.
Add:
CMD ["/bin/bash"]
You can easily test it out by running the following command to get the version of tools installed.
$ docker run --rm codebarber/ansible-packer-terraform aws --version
aws-cli/1.18.19 Python/3.6.9 Linux/4.4.59+ botocore/1.15.19
$ docker run --rm codebarber/ansible-packer-terraform ansible --version
ansible 2.5.1
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/dist-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.17 (default, Nov 7 2019, 10:07:09) [GCC 7.4.0]
$ docker run --rm codebarber/ansible-packer-terraform packer -version
1.5.4
$ docker run --rm codebarber/ansible-packer-terraform terraform -version
Terraform v0.12.23
So just about now, you might be asking yourself, well this is great, but how do I get my config, keys, scripts, templates or playbooks into that image so it can do the work? The nice thing about docker, is its ability to map volumes/folders into the container as it runs. Here is how you can get your ~/.ssh
, ~/.aws
, and current directory mapped into your container.
Lets pretend you are inside your ansible folder on your host that contains the playbooks and roles. In order to run that test-playbook.yml here's the command:
$ docker run --rm \
-w /opt \
-v $(pwd):/opt/ \
-v ~/.aws:/root/.aws \
-v ~/.ssh:/root/.ssh \
codebarber/ansible-packer-terraform ansible test-playbook.yml
Explaining the flags in order:
--rm: tells docker to remove the container after it completes
-w: sets the working directory inside the container to /opt
-v: maps your current working directory into the containers /opt
-v: maps our .aws folder into the containers ${HOME}/.aws
-v: maps our .ssh folder into the containers ${HOME}/.ssh
I hope you find this information useful.
Have a great day!
Top comments (2)
Awesome, thanks!
Very useful,thanks