
Docker Containers aren’t better or worse than Virtual Machines(VMs), but in my experience, the latter is much better. Let me tell you why.
Since their inception, we’ve been told several times that Containers are better than Virtual Machines. Now, I’m here to tell you they aren’t.
Why are they useful?
First of all, let’s recall why these two virtualization tools are very convenient for developers and IT.
In software development teams, many times a team member needs to install the software on a different OS than the application is run.
Software running on an Ubuntu Server might be developed on a MacOS computer. Installing stuff in MacOS is way different than in Ubuntu, and this can cause trouble for developers when trying to run their applications in development mode.
This is where virtualization comes into play. You set up a virtual machine with all necessary dependencies for your software to run, and then give the configuration files to developers, and with a few commands, you can have a proper development environment regardless of the computer or operating system. In many cases with US-based clients like scoreapp.com, Ideaware will set up virtual machines for our engineers to do their best work.
You now have a portable and reproducible environment for many OS.
Docker Containers serve this purpose as well, but they do it in a different and more performant way.
Docker containers vs Virtual machines
One of the main differences between these two kinds of virtualization tools is that virtual machines might need more HDD space upfront, take slower to build up, and can take slower to boot up.
Containers consume less disk space (it depends), are faster to build up, and are faster to launch.
One could say containers are the best of the best. Tools such as Kubernetes might prove it right, and definitely, they have a solid ecosystem and use case.
But what I see is that from the IT or DevOps perspective, they might be awesom,e but in Developer Experience, they’re not.
The following are the reasons why I believe Virtual Machines are better than Docker Containers. They’re mostly based on good personal experience in projects where servers were Virtual Machines and not-so-good projects deployed in a container solution.
Find host or container
With Virtual Machines, whenever you need to debug or test something in a cloud environment, you just need to SSH into a given IP address and that’s it.
When using Docker Containers, you’d have to first get the IP address of the Docker Host and then find the specific container the application was deployed to.
If you have several Docker Hosts, and your app is deployed to several containers, then good luck finding the right container on the right host.
Of course, this can be solved with a script. Code (or have someone to do it for you) a script that:
- Loops through the IP addresses
- Run docker ps
- Grep the output and look for the container ID
- Continue until there’s a match
- If there’s a match, run docker container exec
- Do your debugging
What a PITA. Now, you have this script and you think you won’t have any more problems. Well, what about rotating IP addresses for security reasons?
This is why I think Virtual Machines are better than Docker Containers. In a cloud environment, accessing a virtual machine is WAY easier than just finding a given container.
File uploading
Imagine you are handed a new feature to build. You have to upload files to a file storage. You think about your users, so you set the upload to be run in the background because uploading a file might take some time.
You build it, test it, and try it locally. It works on your machine.
If you push this feature to a Virtual machine-deployed web app, well, it’s going to work fine. If you deploy it to a Docker container-deployed web app, it won’t.
Why? Keep reading.
In the containerization world, one container represents one task, so that they’re small, reproducible, and fast.
With this in mind, your application container only regards running your code, NOT running background jobs. So, if you have background jobs running in a different container, the file upload feature won’t work because the uploaded file won’t exist in the background job container.
Let me slow down:
- App container: runs code and has its own file system.
- Background job container: runs code in the background and has its own file system.
- App container: receives uploaded file via form in a web browser.
- Background job container: picks a file in the expected folder, but it won’t exist because…
The key here is file system differences. The App container file system is not the same as the Background job container file system. When the App container receives the file, it is stored in a temporal path. As this path or folder is not in the Background job directories, the file won’t be found nor uploaded.
And now we have a situation. We either use some kind of Docker Volume or leave the feature as a synchronous one. In my case, I left the feature to work in a synchronous mode.
This is another reason I think Virtual Machines are better than Docker Containers.
Docker Alpine
Previously, I mentioned Docker Containers are a good alternative to Virtual Machines because they consume less disk space. Well, this might not be 100% true.
It happens that before a container, you need a Docker Image. A Docker Image is like a base artifact that describes all the things the container will have when is run. With a Docker Image, you indicate the container operating system, installed software, environment variables, configured files, and command to execute.
Similar to Virtual Machine images, Docker Images consume disk space. If you’re not careful enough, you’ll end up using all your HDD space. You have to be mindful about the base image you use to build your images, what dependencies are downloaded, and know a few key points to use as little disk space as possible when building your images.
In the end, for the developer who only wants a portable environment, this makes no difference than using a virtual machine.
This is when Docker Alpine steps in. What’s Docker Alpine? It’s a Docker Image that has all the important stuff to run Linux and leaves out everything that is not strictly required.
By using Alpine, you can really create slim Docker Images. It brings the benefit that your images will build faster, your containers will be built much faster, and you’ll use less disk space.
Of course, it comes with its own set of problems. I experienced one of them.
Generating PDF files with WKHTMLTOPDF
WKHTMLTOPDF is a tool to generate PDF files out of HTML content. It’s really useful because you can reuse HTML files, and their styling. PDF generation is a complicated domain and WKHTMLTOPDF helps a lot to simplify.
If your software is installed in a Ubuntu server, you’ll be more than fine, as many of the WKHTMLTOPDF dependencies are already available in the OS. However, when your software is being deployed to a Docker Container based on Docker Alpine, you’ll run into problems.
In this situation, Docker Alpine is going to be troublesome. Nothing big, but it’s bothersome.
In the end, to solve this issue with Docker Alpine, I had to read through GitHub issues, read more, and try many options to see what worked and what didn’t. In order to make the tool work in the Docker Containers, I had to install several missing dependencies, more dependencies, and finally WKHTMLTOPDF.
All that trouble could’ve been avoided with Virtual Machines. It wasn’t the first time I used WKHTMLTOPDF. I even have a set of scripts to install it. They’ve always worked in Ubuntu operating systems. They didn’t work in Docker Alpine.
Not that I’m saying that Docker Alpine is bad. It’s just very different and might cause trouble. But this is also a point I think Virtual Machines are better than Docker Containers.
You might think that these points are only valid to me because they’re personal experiences. You’re right.
I’m not saying Virtual Machines will always be better than Docker Containers. The message here is that VMs have been great all those times the Ideaware team used and needed them. Containers are cool, of course, performant, and small. Sure. But in regards to Developer Experience, Virtual Machines still have a lot of good stuff to offer.
From my viewpoint, Virtual Machines > Docker Containers.
Why Ideaware?
Since 2010, we’ve helped US companies scale with top-tier tech talent, not just by filling roles, but by becoming long-term partners in growth.
- We handle sourcing, hiring, onboarding, and retention.
- Start receiving CVs as soon as 48 hours.
- You could meet your new teammate in as little as 8–12 days.
- Our retention rates are 2x the industry average.
Contact us here to discuss your hiring strategy, and we will get in touch with you within 24 hours or less.