Docker is one of the most talked-about technologies of the past year, and adoption rates are increasing rapidly – for good reason. For some developers and operations engineers, Docker may seem confusing and hard to use, but I’d argue that it’s just misunderstood. Here, I’ll explain what Docker is, then walk through why it’s beneficial to use for development and operations.
Docker is an open-source project that automates the development, deployment and running of applications inside isolated containers. Containers allow developers to bundle up an application with all of the parts it needs, such as libraries and other dependencies, and ship it as one package.
Docker is both a daemon (a process running in the background) and a client command. It’s like a virtual machine but it’s different in important ways. First, there’s less duplication. With each extra VM you run, you duplicate the virtualization of CPU and memory and quickly run out resources when running locally. Docker is great at setting up a local development environment because it easily adds the running process without duplicating the virtualized resource. Second, it’s more modular. Docker makes it easy to run multiple versions or instances of the same program without configuration headaches and port collisions. Try that in a VM!
Instead of a single VM or multiple VMs, you might use a tool like Docker Compose. You can link each individual application and supporting service into a single unit and horizontally scale individual services easily without the overhead of a VM or the configuration headache for each one. And it does it all with a single descriptive YAML file, improves the development experience, speeds software delivery and boosts performance.
And because Docker is an open platform, anyone can contribute to its development to build out features that aren’t yet available. Best of all, Docker offers version control (for free!).
With Docker, developers can focus on writing code without worrying about the system on which their code will run. Applications become truly portable. You can repeatably run your application on any other machine running Docker with confidence. For operations staff, Docker is lightweight, easily allowing the running and management of applications with different requirements side by side in isolated containers. This flexibility can increase resource use per server and may reduce the number of systems needed because of its lower overhead, which in turn reduces cost.
Docker has made Linux containerization technology easy to use. In fact, Docker is pretty awesome.
There are a dozen reasons to use Docker. I’ll focus here on three: consistency, speed and isolation. By consistency, I mean that Docker provides a consistent environment for your application from development all the way through production – you run from the same starting point every time. By speed, I mean you can rapidly run a new process on a server. Because the image is preconfigured and installed with the process you want to run, it takes the challenge of running a process out of the equation. By isolation, I mean that by default each Docker container that’s running is isolated from the network, the file system and other running processes.
A fourth reason is Docker’s layered file system. Starting from a base image, every change you make to a container or image becomes a new layer in the file system. As a result, file system layers are cached, reducing the number of repetitive steps during the Docker build process AND reducing the time it takes to upload and download similar images. It also allows you to save the container state if, for example, you need troubleshoot why a container is failing. The file system layers are like Git, but at the file system level. Each Docker image is a particular combination of layers in the same way that each Git branch is a particular combination of commits.
The biggest barrier is current knowledge base. Some developers might not fully understand Docker’s utility or simplicity and might think it’s more complicated than it really is. They may also have other tools in their tool belt, such as Vagrant (a local virtualization technology), virtual servers or Amazon Machine Images (AMIs).
Along those lines, the time needed for hands-on experimentation can be hard to come by. Developers often don’t have the available time or bandwidth to allocate engineering cycles to something new, especially when they already have a working solution. Understandably, they would rather spend time developing their product.
On top of that, it takes a mind shift to translate a current development solution into a Dockerized development solution. For example, if you think of Docker as a virtual machine or a Vagrant machine, you might want to cram a lot of things in it (e.g., services, monitoring software and your application). That would be a mistake. You don’t put many things into a Docker image; instead, you use many Docker containers to achieve the full stack.
In other words, for development you can keep your supporting service containers separate from your application container, and they can all be running on different operating systems and versions while being linked together.
And while you might have extensive experience in implementing AMI-based approaches, you might not have a conceptual understanding of how containers themselves work and behave. A key principle of Docker is that an image doesn’t change. To make changes, you’ll create a new image, which may have the same name and tag. Unlike a virtual machine where every command you run may change the starting point of the next command, with Docker the image never changes, giving you an immutable starting point each time you run the image and the confidence that it will do the same thing each time you run it – no matter where you run it.
Think about a common local development tool like Vagrant. Vagrant mimics your production server, but you may end up with version, supporting technology or network differences. When you put your application in a container, the virtual machine the container’s running on becomes irrelevant, and the container itself is your build artifact.
When you have your application in a Docker container, you can be sure that the code you’re testing locally is exactly the same build artifact that goes into production. There are no changes in application runtime environments. That makes Docker an exceptional tool all the way from development through production.
And, fortunately, Docker isn’t too hard to learn. It’s easy to play with, and the learning curve is relatively small.
So why might it seem hard to use? Probably because you haven’t had the chance to try it yet. In my next blog post, I’ll share some basic Docker commands to get you past the starting gate.