If you work with software, you’ve probably had the “It works on my machine!” problem. Type it into Google and you’ll find jokes, memes, and even t-shirts featuring it. Developers have been haunted for decades by unexpected errors when running code on different machines. Luckily, these days there are some great tools designed to ease this pain.
Today, we’re going to take a look at two of the most popular tools – Docker and Vagrant – to see how they try to solve these problems, and which one you should be using for your development.
Problem – Predictable, Repeatable Development Environments
When running a software application, you are also running all of the libraries it uses, dependencies it has, and the operating system it’s running on. When you run the same application on a different machine, all of those things change, even if that change is very subtle. This is where the problems arise. It could be because you’re running a different operating system version or using a different tool set. It could be something as small as having a different version of PHP installed.
The solution is to be able to somehow whip up an environment that’s guaranteed to be identical every time you run an application, even on a different machine. That’s exactly what virtualization attempts to do.
Docker and Vagrant are based on the idea of “virtual” computing environments, where your application will run in a predictable and repeatable way. The goal is that if your buddy says “It works on my machine”, you know it will work on yours too, and the production server. However, they both attack this problem in very different ways.
What is Vagrant? – Managing Virtual Environments
Vagrant is an open source tool for managing virtual environments. These environments are usually virtual machines. That’s why you run Vagrant with another tool like Virtual Box. Its goal is to solve the problems we just discussed by allowing you to spin up virtual machines that are exactly the same every time. You can be sure that the virtual machine you are running on your local machine is exactly the same as the one you’re running on your staging or production server.
Once you’ve used Vagrant (and another tool like Virtual Box) to set up a virtual server, you run a provisioning script exactly the same on each machine. The provisioning script will:
- Install the correct programs you need (e.g. Node.JS, PHP, etc)
- Correctly set up user permissions
- Configure everything
- Install anything else your application requires
What you end up with is essentially the same environment wherever you set up a virtual machine with Vagrant.
Now, you can run your code or application, and it will run the same on your machine, your buddies machine, and staging and production. You can also push your Vagrant file and code to GitHub, and anyone that pulls in and runs it will be able to recreate the virtual environment easily. When they run your code in this environment, it should act the same every time.
What is Docker? – Containerized Applications
One of the drawbacks of using Vagrant is you have to run an entire virtual machine to run your application. This is very resource intensive and can take a long time to set up and run the provisioning script.
Docker takes a different approach. You use a Docker file (a small ~5-30 line file) to create a Docker image. This Docker image contains:
- All of your project code
- Installments of anything you need (Node.JS, Rails etc)
- Any configurations you need
It’s basically your complete application and all of its dependencies wrapped up into one neat package. Then you can run this image as a container on any machine running Docker. You don’t need a new virtual machine for each container, just one, as they are designed to run on top of a machine. Then, you can run as many Docker containers as you like on that virtual machine – as long as you have enough processing power and RAM.
You could run a Docker container of a Rails app with a Rails installation bundled up into it, while also running a container of a Node.JS application. You wouldn’t need to install Rails or Node. Both would have their own installations contained within them. They are completely separate from each other but share an operating system kernel.
Docker is gaining massive popularity as Steven J. Vaughan-Nichols puts it “I can’t think of a single company of any size that’s not at least looking into moving their server applications to containers in general and Docker in specific.”
Vagrant sets up a predictable, repeatable environment (e.g. a virtual machine) for you to run your application. You run your code into an environment and can expect it to behave a certain way.
Docker allows you to create images that ARE your project code. You use a Docker image to build an environment that you can run anywhere. If you can run Docker, you can run your application and it will work every time.
Vagrant helps you set up entire virtual machines to run your applications, while Docker helps you manage containers that can run on top of a virtual machine.
So which one should you use for your development?
Docker vs Vagrant For Development
In software development, the answer to the question “which is better” is usually “it depends”. And that’s true for Docker vs Vagrant. The best way to find out which you should use is to look at the advantages and disadvantages of each and decide which are more valuable to your project.
Setting Up – Vagrant
Setting up a Vagrant development environment and workflow is much simpler than Docker. It’s also easier to get your head around. If you simply need a way to set up and configure a virtual machine and aren’t too worried about RAM, startup times, or collaboration (e.g. for a WordPress installation), Vagrant might be best for you.
Collaboration – Docker
Collaboration is where Docker really shines. You could say that Docker does for containers what GitHub does for source code control. Docker Hub is like the GitHub for Docker images. Once you’ve made an image, you can push it to your Docker Hub repository. Now, anyone can pull that container and run your containerized application with its complete environment anywhere. All you need is to be running Docker. It’s really incredible!
Resource Isolation – Vagrant
While Docker containers act kind of like virtual machines, they really aren’t. Docker containers share an operating system and a kernel. That means they are completely separated from each other logically. For some applications, that’s simply not acceptable. In those cases, Vagrant is going to be a better option. If you aren’t sure if it’s going to be a problem, you probably don’t need to worry about it.
Resources and Startup Times – Docker
Docker is built on container technology that is simply faster and less resource intensive than virtual machines. Containers can be whipped up in milliseconds rather than minutes, and require megabytes of RAM rather than Gigabytes. While you can use Vagrant to run multiple instances of the same virtual machine to run multiple applications, doing with containers is going to have significantly better performance.
|Virtualization||Virtual machine||Linux container|
|Resource isolation||Strong||Weak (shared kernel)|
|Image build time||10+ minutes||mins|
|Sharing||Vagrant Cloud||Docker Hub|
Using Docker With Vagrant
You might have figured out by now that Docker and Vagrant aren’t in direct competition with one another. In fact, they can be used together (and often are). You can use the Vagrant Docker Provisioner to “automatically install Docker, pull Docker containers, and configure certain containers to run on boot.”
This is a great way to get started, as you can use Vagrant to automatically setup and install Docker for you! Check out the docs here. For the more advanced Vagrant developers, you can also use Docker as a provider. I won’t get into here, but check out the Vagrant docs for more info.
Knowing how to set up a predictable, repeatable computing environment is really important these days. We’ve looked at two ways to tackle this problem head on, and why you might choose either of them. Docker is gaining popularity at an astonishing rate now in 2017. If you still aren’t sure where to start, take a look at this tutorial on how to get started with Docker. Alternatively, you can find a development team to set up everything for you.
So get started and hopefully next time your colleague says “it works on my machine” you know it will work on yours too!