Docker and Ansible Solve 2 Different Problems and They Can Be Used Together
There is some overlap on what each of these tools can do for you, but at the end of the day it makes a lot of sense to use both together.
If you’re just starting to learn about Docker and are familiar with configuration management tools such as Ansible, Salt Stack, Puppet or Chef then you might be wondering what makes Docker different.
At a quick glance, they are not too different. I mean, if you wanted to install nginx on your server, you could reach for an Ansible role or Docker image to do so. Both of them will ensure that nginx is running on your server, so what makes them different?
What is Ansible?
Ansible is a configuration management tool. Generally, configuration management tools give you a consistent and reliable way to ensure that your system is at the desired state you want it to be.
Declare What Gets Ran on Your Server
For example, instead of logging into your server and manually running 20 ad-hoc commands to set up a few things on your server, you would declare those 20 commands with a tool such as Ansible.
These commands could be anything. Perhaps it’s to set up a deploy user on your server, or install and configure a service like nginx. The possibilities are endless.
Idempotent by Default
Another upside to using Ansible is that it will only make these changes on your server if it has to. For example, if you manually extracted a zip file a few times, then the entire contents of that zip file will be extracted each time you ran the command.
With Ansible, you could tell it to only extract that zip file if it hasn’t been extracted already. Sure, you could wrap your unzip command in an if statement without Ansible, but when you want to do 150 different things to your server, that strategy becomes extremely tedious and error prone.
Basically Ansible lets you say “I have 1 or more servers and I would like to set up a bunch of things on that server. When I run Ansible, this server will match the specifications I supplied. If I run Ansible again, nothing will change unless I made a change to the specifications”.
How It Works
The gist of it is, you declare YAML based tasks and then Ansible processes and runs them.
For example, here’s how you could install nginx with Ansible:
- name: Install nginx apt: name: 'nginx' state: 'present'
In addition to this, you’d likely end up writing a dozen other tasks to do standard “nginx things”, such as deleting the default nginx site, setting up your custom configurations and configuring your system so that nginx starts on boot.
But there’s a couple of problems using Ansible to install nginx (or ANY service):
apt, which means this will only work if you’re running a Debian based distribution of Linux. You would need a different task if you were running CentOS or something else.
When you run this task, it’s “really” happening at run-time. Imagine the scenario where you test this on a staging server and it works, and then you run it in production but it fails because an APT mirror happens to be down. That is something you cannot predict, but since the installation is happening at deploy time, there’s no way to know if it will work for sure.
Different versions of a distro have different versions of nginx. For example Ubuntu 16 might have nginx 1.9 where as Ubuntu 14 has an older version. To combat this, you have to jump through hoops to set up custom upstreams and pin versions for each package you install.
Honestly, the first problem isn’t that big of a deal since it’s not like you’re changing distros of Linux all the time but the other 2 problems are a serious concern for any system.
It’s on You
You’re also responsible for configuring all of your services yourself. You could reach for third party Ansible “roles” but there are no official roles. The best you can do is find an author who you like and use their stuff, but who knows how long they will maintain their roles.
For example, ~3 years ago I wrote about 25 Ansible roles. A lot of them haven’t been touched in 2+ years because I do not use them personally. I do my best to maintain the roles I continue to use now, but my point is, if you use 3rd party roles, you’re depending on random community authors.
How Is Docker Different than Ansible?
First up, we need to define what Docker lets you do:
- Package up applications in a consistent way
- Build, test, debug and deploy your apps
- Distribute and scale your applications
Long story short, it’s a way for you to build and distribute your applications. Docker is not a configuration management tool.
Build Once, Ship Anywhere
Instead of declaring what a system should be in YAML and then running it, you simply build your services into individual Docker images, and then run those images on your server(s).
You can take a Docker image and run it on any operating system that’s capable of running Docker, which at the time of writing this article is every major distribution of Linux. But don’t worry, there are ways to run Docker on MacOS and Windows too.
The Same nginx Example from Above but with Docker
There’s no YAML to define if all you want to do is run nginx. All you would do is, run a specific Docker command once you have Docker installed. For example:
docker run --rm --name nginx -p 80:80 nginx:1.13-alpine.
Congrats nginx is now up and running. Don’t believe me? Try going to
http://localhost or your Docker Machine IP address which is likely
There’s a couple of interesting things to note here:
You don’t know or care about what distro of Linux nginx is running under. Technically you do know it’s running on Alpine because we’re supplying the version in the command, but you don’t need to know how it works. Also, it will work on any Linux distro that’s running on your server.
nginx was “working” long before you ran it. nginx was already built into a thing called a Docker image, and the above command just ran it. There’s a 0% chance of failure in staging or production, because you’re moving a fully working service from 1 environment to the next.
You always get the same version of nginx. Since we’re not depending on a specific package, you’ll always get the version that you defined when you ran it.
Thousands of Services Are Waiting for You to Use Them
In the above case we used the official nginx Docker image, which means that it’s being maintained by not only Docker, but someone working for nginx.
The image has been rigorously tested and was created with the highest standards. It’s also very well maintained. My point is, both Docker and nginx are vested in this image. Their brands depend on it, so you can be sure it’s top notch.
You can also use community images too, but that’s discussion for another time.
When Should You Use Docker or Ansible?
Now that you know a little bit about each tool, it’s time to decide when you should use Docker or Ansible. If I were you, I would just use both because they each solve different problems.
When to Use Docker
I like to think of it like this. If I’m running a service, such as nginx, Redis, PostgreSQL, or my own web applications then I’m most definitely going to use Docker.
This works great in development, testing and production because the same images get ran across each environment. If I’m hacking away on some code on my dev box then I can be confident it will work the same way in production.
Docker gives you a number of tools to help move these images between servers, and even perform complicated tasks such as load balancing services and performing rolling updates.
When to Use Ansible
I like to use Ansible for things that exist at the server level but aren’t necessarily processes that run. For example, if I wanted to create a deploy user on the system, then it makes sense to use Ansible. This is something that needs to exist on the main system, not inside of Docker.
Ansible is also great for bootstrapping Docker itself. That means installing Docker, along with Docker Compose or any other Docker related tools you need to configure (such as Docker Swarm). For example, here’s my Ansible role to install Docker / Docker Compose.
Basically, I would reach for Ansible for performing tasks that set up core functionality for the server to do its thing. That includes the above, along with doing things like hardening SSH’s configuration to make it more secure, or copying over config files that I plan to volume mount with Docker.
Once that server is production ready, then I run my custom services on it with Docker.
What are you using Docker and Ansible together for right now?