Home About Me

When VMware 10 Fails on CentOS 8: a Fix, and Why Docker Started Looking More Practical

While installing a CentOS virtual machine in VMware, I ran into the error end Kernel panic - not syncing: Fatal exception.

Kernel panic error screen

The setup in question was VMware 10 with a CentOS 8 image. In that combination, installation failed with the kernel panic above. Changing the image to CentOS 7 allowed the system to install normally. A more direct fix is to upgrade VMware 10 to VMware 12, which also resolves the compatibility issue.

So in practice there are two workable options:

  • upgrade VMware 10 to VMware 12
  • keep the older VMware version and use a CentOS 7 image instead of CentOS 8

I ended up solving it by switching to CentOS 7.

When looking for the CentOS 7 download, it was easy to notice that the project offered several variants besides the regular ISO, including entries such as Cloud, Containers, and Vagrant. That naturally raises a practical question: if the goal is just to run isolated environments, is a full virtual machine always necessary, or would Docker be a better fit?

Why Docker and virtual machines feel similar, but work very differently

Docker is often grouped with virtualization tools because it also provides isolation for applications and environments. But the mechanism is not the same as a traditional virtual machine.

Below are the architecture diagrams for a virtual machine and for Docker:

Virtual machine architecture Docker architecture

The key difference is that the Guest OS layer and Hypervisor layer used by virtual machines are replaced in Docker by the Docker Engine.

In a virtual machine:

  • the Guest OS is a complete operating system with its own kernel
  • the Hypervisor acts as the hardware virtualization layer
  • CPU, memory, and I/O devices are virtualized before the guest system can use them

That means isolation is achieved by giving each virtual machine its own independent operating system environment.

How a virtual machine virtualizes hardware

For CPU virtualization, the hypervisor maintains virtual CPU state for each guest. It tracks register values and steps in when privileged operations require control over the virtualized processor state. In many cases, guest code can still run directly on hardware, but once kernel-level operations touch sensitive CPU state, the hypervisor must intervene.

For memory virtualization, the hypervisor uses a shadow page table. Under normal conditions, a page table translates virtual memory into physical memory. In a virtualized environment, though, the guest's “physical memory” is itself virtual, so translation effectively becomes:

virtual memory -> guest physical memory -> actual physical memory

For I/O virtualization, the hypervisor may trap memory access or page faults that correspond to devices, simulate the device in software, and return the result. For example, when the guest thinks it is writing to a disk, the hypervisor may actually write data into a file on the host system, and that file serves as the virtual disk.

How Docker isolates without a guest OS

Docker is much lighter in comparison. It does not create a full independent operating system for each container. Instead, it relies on Linux kernel features already present on the host system:

  • Namespaces isolate system views such as processes, networking, and mounts
  • Cgroups limit resource usage
  • Images and filesystem layering isolate the root filesystem environment

In other words, Docker avoids the extra guest OS layer and avoids a hypervisor-based hardware abstraction for every workload.

From that design, two broad conclusions follow.

First, Docker has fewer abstraction layers than a virtual machine. Since containers use the host kernel directly, applications inside them access the real hardware more directly. That usually gives Docker an efficiency advantage in CPU and memory usage.

Second, Docker does not need to boot a guest operating system when creating a new environment. Starting a virtual machine means loading an entire OS kernel, which takes noticeable time and consumes significant resources. Starting a Docker container usually takes only seconds. On one physical machine, it is realistic to run hundreds or even thousands of containers, while the number of virtual machines is far smaller.

Computing performance: Docker vs. virtual machines

The performance comparison discussed here is based on data measured on an IBM x3650 M4 server. Its main hardware specifications were:

  1. two Intel Xeon E5-2655 processors running at 2.4-3.0 GHz
  2. each processor had 8 cores, for a total of 16 cores
  3. 256 GB RAM

The compute benchmark used Linpack.

Compute performance comparison

From left to right, the figure shows results for bare metal, Docker, and a virtual machine. Docker's compute performance is almost unchanged compared with the physical machine, while the virtual machine shows a much more obvious loss. The drop for the virtual machine is around 50%.

That gap has two main causes.

One is the extra virtualization layer. Applications running in a VM perform calculations through virtualized hardware, especially a virtual CPU managed by the hypervisor.

The other is that compute-heavy applications are often optimized for specific CPU architectures. Virtualization can hide or reshape the real hardware layout, making those optimizations less effective or even counterproductive. In the experiment described, the physical system's architecture differed from how the virtual CPU topology was presented to the guest. For instance, the actual machine used a NUMA layout, while the virtual machine exposed a simplified CPU view. As a result, the application could not optimize itself for the real hardware as effectively, and performance dropped.

Memory access performance: where the differences show up

Memory access is more complicated than raw CPU performance because there are different access patterns.

The two main cases are:

  1. large-scale sequential reads and writes over continuous memory blocks
  2. random memory access

Before looking at the test results, the important structural difference is this: applications in a virtual machine go through two levels of address translation, while applications in Docker use the host model more directly.

Memory access model for Docker and virtual machines

Because of that, memory access inside a VM carries a higher translation cost.

Sequential memory bandwidth

The following figures show memory bandwidth results. The left figure is for workloads running on one CPU, and the right figure is for workloads running across two CPUs. Units are GB/s.

Memory bandwidth on one CPU Memory bandwidth on two CPUs

Here the gap between Docker and virtual machines is not very large. The reason is that sequential memory access benefits from kernel optimizations such as prefetching. Since the addresses are continuous and accessed in bulk, the number of virtual-to-physical mappings is relatively small, and the main bottleneck becomes the physical memory hardware itself.

So for memory bandwidth tests, Docker and VMs can look fairly close.

Random memory access

If the earlier explanation is correct, the difference should become more visible when memory access is random, because random access increases the number of address translations.

That is exactly what the test results show:

Random memory access on one CPURandom memory access on two CPUs

In the one-CPU case, container performance is clearly better than virtual machine performance for random memory access.

Interestingly, once the test runs across two CPUs, the gap becomes much less obvious. The explanation is that memory synchronization and coordination become more complex when two CPUs are reading and writing memory at the same time. That overhead affects even the physical machine itself. In that scenario, the performance penalty caused by multi-CPU memory coordination is so large that it masks much of the difference between Docker and VMs.

Startup time and resource cost

Performance under load is only part of the story. One of Docker's biggest practical advantages is the cost of starting a new environment.

A virtual machine must go through OS bootstrapping and carry the overhead of an entire guest operating system. Docker skips that by using the host kernel directly. As a result:

  • containers can be started within seconds
  • the system resource cost is much lower
  • large numbers of isolated environments can be created quickly

That is why Docker has been especially attractive in elastic cloud platforms and automated operations scenarios, where rapid provisioning matters as much as runtime performance.

Where Docker is weaker than a virtual machine

Docker is not a perfect replacement for virtual machines. It has several disadvantages that matter depending on the use case.

1. Weaker resource isolation

Docker relies on cgroups to limit resource consumption, but that is not the same as the harder isolation offered by a VM. It can cap resource usage, yet it cannot fully prevent other workloads from affecting the resources available to a container.

2. Security concerns

Docker, in the form described here, does not distinguish container operations in a fine-grained way based on the actual initiating user. If a user has permission to operate Docker, that user can perform broad actions on containers, even if those containers were created by someone else. That creates an obvious security risk in multi-user environments.

3. Compatibility and rapid changes

Docker was evolving quickly, and some important features depended on newer Linux kernels. That means version compatibility can become an issue, especially on older systems.

A practical takeaway

If VMware 10 throws end Kernel panic - not syncing: Fatal exception during a CentOS 8 installation, the immediate fix is straightforward: upgrade VMware to version 12, or switch to a CentOS 7 image.

But once that problem appears, it also highlights a broader decision. If the task really needs a full operating system with stronger isolation, a virtual machine still makes sense. If the goal is fast deployment, lower overhead, and near-native performance in many scenarios, Docker can be a more efficient choice.