Docker Tutorials

Docker vs Virtual Machines

18 min

Docker vs Virtual Machines

What is the Difference Between Docker and Virtual Machines?

1. Introduction

[!NOTE] Question What is the difference between Docker and virtual machines?

What we're trying to achieve: Understand the fundamental differences between containerization (Docker) and virtualization (VMs), and when to use each technology.

Goal/Aim: Learn how Docker containers and VMs differ in architecture, performance, use cases, and resource utilization so you can make informed decisions about which technology to use.


2. How to Solve (Explained Simply)

Think of an apartment building vs separate houses:

Virtual Machines (Separate Houses):

  • Each house has its own foundation, walls, plumbing, electrical system
  • Complete independence but takes lots of space and resources
  • If you want 5 houses, you need 5 complete sets of everything
  • Each house can be completely different (different architecture)

Docker Containers (Apartment Building):

  • All apartments share the same foundation (building infrastructure)
  • Each apartment is isolated but shares common resources
  • Much more efficient use of space
  • Can fit many apartments in the space of a few houses
  • All apartments must be compatible with the building structure

Real-world analogy:

VM: Imagine carrying a full computer tower, monitor, keyboard, and mouse everywhere you go just to run one app.

Container: Imagine carrying just a USB drive with your app that works on any computer.


3. Visual Representation

🏗️ Architecture Comparison

⚠️ Virtual Machines

Physical Server
Host Operating System
Hypervisor
VM 1
App A
Libs
Guest OS
~2 GB
VM 2
App B
Libs
Guest OS
~3 GB
VM 3
App C
Libs
Guest OS
~2 GB
VM 4
App D
Libs
Guest OS
~2 GB

✅ Docker Containers

Physical Server
Host Operating System
Docker Engine
C1
App A
Libs
~100 MB
C2
App B
Libs
~200 MB
C3
App C
Libs
~150 MB
C4
App D
Libs
~100 MB
+More
Many
More...

⚡ Boot Time Comparison

VM Boot 60+ seconds
BIOS → Bootloader → Kernel → Init → Services → Ready
Container Boot ~1 second
Start → Ready

4. Requirements / What Needs to Be Gathered

Prerequisites:

  • Understanding of operating systems
  • Basic knowledge of computer architecture
  • Familiarity with the concept of virtualization
  • Understanding of processes and resources (CPU, RAM)

Conceptual Requirements:

  • Kernel: The core of an operating system
  • Hypervisor: Software that creates and runs VMs
  • Process Isolation: Separating running programs
  • Resource Allocation: How CPU/RAM is distributed

5. Key Topics to Consider & Plan of Action

Key Differences to Understand:

  1. Architecture

    • How they're built
    • Resource sharing model
    • Isolation mechanisms
  2. Performance

    • Startup time
    • Resource overhead
    • Runtime efficiency
  3. Portability

    • How easy to move
    • Platform dependencies
    • Compatibility
  4. Use Cases

    • When to use each
    • Strengths and weaknesses

Comparison Plan:

text
Step 1: Understand VM Architecture
How hypervisors work, Guest OS concept

Step 2: Understand Container Architecture
How containers share kernel, process isolation

Step 3: Compare Resource Usage
Size, speed, efficiency metrics

Step 4: Identify Use Cases
When VMs are better, when containers are better

Step 5: Hybrid Approaches
Using both technologies together

6. Code Implementation

Virtual Machine Example (Using Vagrant)

ruby
# Vagrantfile - Creates a VM
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"

  config.vm.provider "virtualbox" do |vb|
    vb.memory = "2048"  # 2GB RAM
    vb.cpus = 2
  end

  config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    apt-get install -y nginx
  SHELL
end
bash
# Start VM (takes 2-5 minutes)
vagrant up

# SSH into VM
vagrant ssh

# Stop VM
vagrant halt

# Destroy VM
vagrant destroy

Docker Container Example (Same Application)

dockerfile
# Dockerfile - Creates a container image
FROM ubuntu:20.04

RUN apt-get update && \
    apt-get install -y nginx && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
bash
# Build image (takes 30 seconds - 1 minute first time)
docker build -t my-nginx .

# Start container (takes 1-2 seconds)
docker run -d -p 8080:80 my-nginx

# Stop container (instant)
docker stop <container-id>

# Remove container (instant)
docker rm <container-id>

Performance Comparison Script

python
# performance_comparison.py
import time
import subprocess

def time_vm_startup():
    """Time VM startup (simulated)"""
    start = time.time()
    # VM would take 60+ seconds
    print("VM would take ~60 seconds to boot")
    return 60

def time_container_startup():
    """Time container startup"""
    start = time.time()
    subprocess.run(["docker", "run", "-d", "nginx"],
                   capture_output=True)
    end = time.time()
    return end - start

def compare_sizes():
    """Compare image/VM sizes"""
    vm_size = 1500  # MB (typical minimal Ubuntu VM)

    # Get Docker image size
    result = subprocess.run(
        ["docker", "images", "nginx", "--format", "{{.Size}}"],
        capture_output=True, text=True
    )
    container_size = result.stdout.strip()

    print(f"VM Size: ~{vm_size} MB")
    print(f"Container Size: {container_size}")

if __name__ == "__main__":
    print("=== Startup Time Comparison ===")
    vm_time = time_vm_startup()
    container_time = time_container_startup()
    print(f"Container is {vm_time/container_time:.0f}x faster!")

    print("\n=== Size Comparison ===")
    compare_sizes()

Resource Monitoring

bash
# Monitor VM resources (VirtualBox example)
VBoxManage showvminfo "VM_NAME" | grep Memory
VBoxManage showvminfo "VM_NAME" | grep CPU

# Monitor Container resources
docker stats

# Compare resource usage
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"

7. Things to Consider

Detailed Comparison Table:

Aspect🖥️ Virtual Machines🐳 Docker Containers
Size GBs (1-10+ GB) MBs (10-500 MB)
Boot Time Minutes (1-5 min) Seconds (1-10 sec)
Performance Slower (hypervisor overhead) Near-native speed
Isolation Complete (separate kernel) Process-level (shared kernel)
OS Support Any OS on any host Must match host kernel
Security Stronger isolation Good but shares kernel
Portability Less portable (large files) Highly portable
Resource Usage Heavy Lightweight
Density 10-20 VMs per host 100+ containers per host
Networking Slower (virtual NIC) Faster (same network stack)
Storage Slower (virtual disk) Faster (layered filesystem)

Quick Decision Matrix:

🎯 Decision Flow Chart

Need different OS?
Use VMs
↓ No
Need maximum isolation?
Use VMs
↓ No
Need rapid scaling?
Use Containers
↓ Yes
Building microservices?
Use Containers
↓ Yes
Want fast deployments?
Use Containers

Summary

Virtual machines and Docker containers solve similar problems but in fundamentally different ways. VMs provide complete isolation by running full operating systems on top of a hypervisor, making them heavier but more secure and versatile. Containers share the host OS kernel and isolate at the process level, making them lightweight, fast, and efficient. Choose VMs when you need different operating systems, maximum isolation, or are working with legacy applications. Choose containers for microservices, rapid deployment, and when you need to run many applications efficiently on the same infrastructure. Many modern systems use both technologies together to leverage the strengths of each.

Press j for next, k for previous