Docker – Building containers using Ansible

Docker – Building containers using Ansible


Have you thought about building Docker containers using some Ansible role(s) or playbook(s) you may already be using for your regular automated deployments? Well this is something I have been going back and forth on. Whether to disregard existing Ansible roles  I have created to deploy applications and services with or to start from scratch to build Docker containers. So I wanted to share a quick example of how you can do this if interested. The only downside is that the Docker image is a little fat because of the Ansible installation within the container. The plus to this is that Ansible is already installed in the container and you can actually reconfigure your containers with different variables ( based on variables in your Ansible role(s) or playbook(s) ) using docker exec commands. But that is debatable IMHO because I would possibly rather use Ansible to spin up the containers passing the ENV variables which are defined as part of the container. So the real benefit here would be to leverage your existing role(s) and playbook(s) that you use for your non containerized instances to build your Docker containers.

So with the above being said let’s take these methodologies and build a MySQL container.

As I mentioned above, I already have an Ansible role to deploy MySQL so I will be leveraging that.

If we look at the directory structure of the files that will be copied into our Docker container during the build.

vagrant@node-1:/vagrant/containers/mysql-ansible$ tree
.
├── ansible_tasks
│   ├── playbook.yml
│   └── requirements.yml
└── Dockerfile


1 directory, 3 files

And below are the contents of the files which will be copied.

playbook.yml

---
- hosts: localhost
  become: true
  vars:
    - mysql_allow_remote_connections: true
    - mysql_docker_install: true
  roles:
    - role: ansible-mysql
  tasks:

requirements.yml

---
- src: https://github.com/mrlesmithjr/ansible-mysql.git

And our Dockerfile to build from (Using Ansible)

FROM ubuntu:14.04

MAINTAINER Larry Smith Jr. <mrlesmithjr@gmail.com>

#Update apt-cache
RUN apt-get update

#Install pre-reqs for Ansible
RUN apt-get -y install git python-dev python-pip

#Install Ansible
RUN pip install ansible

#Copy Ansible tasks
COPY ansible_tasks /opt/ansible_tasks

#Install Ansible role(s)
RUN ansible-galaxy install -r /opt/ansible_tasks/requirements.yml

#Run Ansible playbook
RUN ansible-playbook -c local /opt/ansible_tasks/playbook.yml

#Clean-up packages
RUN apt-get -y clean && \
    apt-get -y autoremove

#Clean-up temp files
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

#Expose port(s)
EXPOSE 3306

#Process start-up
CMD ["/usr/bin/mysqld_safe"]

Now we can build our container..

docker build -t mysql-ansible .

Now if we do a standard Docker install without using Ansible using the below Dockerfile

FROM ubuntu:14.04

MAINTAINER Larry Smith Jr. <mrlesmithjr@gmail.com>

#Update apt-cache
RUN apt-get update

#Install MySQL
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install mysql-server

#Clean-up packages
RUN apt-get -y clean && \
    apt-get -y autoremove

#Clean-up temp files
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

#Expose port(s)
EXPOSE 3306

#Process start-up
CMD ["/usr/bin/mysqld_safe"]

And now build without Ansible.

docker build -t mysql .

And if we do a quick look at our Docker images to compare the differences in the image sizes…

vagrant@node-1:/vagrant/containers/mysql$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql               latest              26c155e1472e        4 seconds ago       339.4 MB
mysql-ansible       latest              549207bd1f0e        14 minutes ago      636 MB
ubuntu              14.04               07c86167cdc4        3 hours ago         188 MB

As you can see there is quite a bit of bloat using Ansible but it may or may not be worth it. So YMMV.

So there you have it and hopefully you found this to be of some use. And I am very interested in your thoughts and perspecitves.


 

Update…

After posting this I thought I would see if there was a difference in the image size if I were to install Ansible via apt ppa instead. Being that I installed Ansible via pip in the previous comparison. So here are those results. (The image names are different than the above original but you can compare the image sizes to validate)

Using the following Dockerfile…

FROM ubuntu:14.04

MAINTAINER Larry Smith Jr. <mrlesmithjr@gmail.com>

#Update apt-cache
RUN apt-get update

#Install pre-reqs for Ansible
RUN apt-get -y install git software-properties-common

#Adding Ansible ppa
RUN apt-add-repository ppa:ansible/ansible

#Update apt-cache
RUN apt-get update

#Install Ansible
RUN apt-get -y install ansible

#Copy Ansible tasks
COPY ansible_tasks /opt/ansible_tasks

#Install Ansible role(s)
RUN ansible-galaxy install -r /opt/ansible_tasks/requirements.yml

#Run Ansible playbook
RUN ansible-playbook -c local /opt/ansible_tasks/playbook.yml

#RUN pip uninstall ansible -y

#RUN apt-get -y purge git python-dev python-pip

#Clean-up packages
RUN apt-get -y clean && \
    apt-get -y autoremove

#Clean-up temp files
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

#Expose port(s)
EXPOSE 3306

#Process start-up
CMD ["/usr/bin/mysqld_safe"]

And now building…

docker build -t mysql-ansible-apt .

And below are the results…

vagrant@node-1:/vagrant/containers$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysql-ansible-pip   latest              b7b7f93506c6        9 seconds ago       636 MB
mysql-ansible-apt   latest              f9e313ffc5fa        2 minutes ago       504.9 MB
mysql               latest              9ac234dd93bf        4 minutes ago       339.4 MB
ubuntu              14.04               07c86167cdc4        3 hours ago         188 MB

And as you can see from above we indeed saved 132MB installing Ansible via apt using their ppa repository.

Enjoy!

About Larry Smith Jr.

vExpert 2013-2016 | Old-School coder coming back around to my roots #DevOPS and #automation | #Ansible junky!

4 thoughts on “Docker – Building containers using Ansible

  1. If you’re looking at producing the smallest image possible, you need to look at reducing the number of layers and know exactly how they work first.

    For exemple, you should not separate the apt-get clean and the rm -rf parts of your install command, if you do, what happen at the layer created through the “RUN rm -rf ….” part (or the apt-get clean, which is basically the same thing) is just “tombstone” files being referenced, not actually removes, because they exists in a previous layer.

    That why, when looking at the official images (like mysql: https://github.com/docker-library/mysql/blob/a93628500589d5a584f523fd168360ec16d81655/5.5/Dockerfile) you see multiple lines with apt-get updates && apt-get install […] && rm-rf on a single line, because that way the layer where you’re actually installing your binaries are as slim as possible.

  2. You could install ansible in a different container and then mount this container on the container you want to provision. I have seen this with chef. You would lose ability to rerun ansible though.

  3. Pingback: Docker - Ansible - ELK Stack - EverythingShouldBeVirtual

Leave a Reply

Your email address will not be published. Required fields are marked *

*