Recently, a friend told me he wanted to set up a homelab and his first question to me was, “Should I install Proxmox or Docker?” This question actually stems from a fundamental misunderstanding, because Proxmox and Docker are not competing technologies; on the contrary, they are two different layers that complement each other. Many people entering the homelab world are confused about this, so I wanted to explain what these two do and where it makes more sense to start a homelab adventure, based on my 20 years of field experience.
In this post, I will detail what Proxmox and Docker are, their fundamental differences, how I use them on my own servers and in production ERP, and what strategy should be followed for a homelab. In fact, the most efficient homelab setup often involves using these two technologies together.
The Wrong Question When Starting a Homelab Journey: Are Proxmox and Docker Rivals?
When you decide to set up a homelab, you need to consider the software layer as much as the hardware selection. People generally want to use their single physical server as efficiently as possible. At this point, the names Proxmox and Docker frequently come up, and they perceive it as if they have to choose one and give up the other. However, this situation is similar to asking, “Should I buy a house or a car?”; both serve different needs and are not interchangeable.
In my experience, such questions usually arise from confusing the fundamental layers of technologies. Proxmox is a “Hypervisor” that runs on physical hardware, while Docker offers “Container” technology at the operating system level. In other words, Proxmox allows you to partition your physical server into multiple virtual servers, while Docker helps you isolate your applications within these virtual servers. Understanding this difference is the first step to correctly building your homelab architecture.
What is Proxmox and Why is it Preferred in a Homelab?
Proxmox VE (Virtual Environment) is an open-source server virtualization platform. It is based on KVM (Kernel-based Virtual Machine) and LXC (Linux Containers) technologies. In short, when you install Proxmox on your physical server, you can partition that server into multiple virtual machines (VMs) or lightweight containers (LXCs). I have been using Proxmox for years in my own homelab and even in the test environments of some older client projects. When I want to run Windows, Linux servers, and even different Linux distributions simultaneously on a single physical server, Proxmox is my go-to solution.
Proxmox’s biggest advantage is its efficient sharing of physical resources (CPU, RAM, disk, network cards) among virtual machines and its easy management through a central web interface. For example, while developing the backend for my own side products, I can install a PostgreSQL server on a separate Debian VM on one side and run a FastAPI application on another Ubuntu VM. This way, a software crash or resource consumption on one doesn’t directly affect the other. Furthermore, with Proxmox’s snapshot and backup features, I can easily ensure the security of my critical systems. A few years ago, when I experienced a disk failure, I was able to restore all my virtual machines to a new disk within just a few hours thanks to Proxmox’s automatic backup feature.
# Example of creating a new LXC (Linux Container) in Proxmox
# This command creates an Ubuntu 22.04 LTS-based container with 512MB RAM and 4GB disk.
# This is an ideal solution for lightweight services.
pct create 101 local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst --hostname my-lxc --memory 512 --rootfs local-lvm:4 --unprivileged 1 --cores 1
What is Docker and Why is it Used in Application Development?
Docker is a platform used to package applications and their dependencies into lightweight, portable, and isolated units called “containers.” Unlike Proxmox, Docker virtualizes the operating system, not the physical hardware. This means Docker runs on an already running operating system (e.g., a Linux VM). Docker has been an indispensable tool in my production ERP development process or when setting up the backend services for my Android spam application. As an application developer, it allows me to keep my development, testing, and production environments exactly the same.
Docker’s main benefit is that it eliminates the “it worked on my machine” syndrome. You include all of an application’s dependencies (libraries, settings, binaries) in a single Docker image. You can run this image on any server (your local machine, inside your Proxmox VM, in the cloud), and it will behave the same everywhere. Last year, when I encountered an unexpected error in an API service due to a Python version, I was able to identify and fix the problem in 15 minutes thanks to the precise versioning within the Docker container. If I hadn’t used Docker, I would have risked corrupting the global Python environment on that server.
# A simple Nginx Dockerfile example
# This file defines how we run the Nginx web server inside a container.
FROM nginx:latest
COPY ./nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
How Proxmox and Docker Work Together in Homelab Scenarios?
Let me explain exactly what I mean when I say Proxmox and Docker complement each other. In a homelab scenario, you typically have a single physical server. You install Proxmox directly on this server. Proxmox is the operating system and hypervisor layer on top of this physical server. Then, from Proxmox’s web interface, you create multiple virtual machines (VMs) or LXCs. For example, a Debian VM, an Ubuntu LXC, or even a Windows Server VM.
This is where Docker comes in: you install Docker inside these virtual machines. For instance, you install the Docker Engine inside your Debian VM and run all your applications (Nginx reverse proxy, PostgreSQL database, your custom services, Plex media server, etc.) as Docker containers within this VM. This architecture provides you with both hardware-level isolation (between different operating systems with Proxmox) and application-level isolation (between applications within the same operating system with Docker). I use this structure for most of my side products; I have a Linux VM on Proxmox, and all my services run in Docker Compose stacks within that VM. This gives me the flexibility to move, back up, or allocate specific resources (CPU, RAM) to the VM.
graph TD;
A["Physical Server (Bare-Metal)"] --> B["Proxmox VE"];
B --> C["VM: Debian Server"];
B --> D["VM: Ubuntu Server"];
C --> E["Docker Engine"];
E --> F["Container: Nginx"];
E --> G["Container: PostgreSQL"];
E --> H["Container: My Own Application"];
D --> I["Docker Engine"];
I --> J["Container: Jellyfin"];
I --> K["Container: Home Assistant"];
subgraph "Proxmox Layer"
B
end
subgraph "VM Layer"
C
D
end
subgraph "Docker Layer (inside VM)"
E
F
G
H
I
J
K
end
This diagram shows how Proxmox runs on a physical server, how multiple VMs are hosted within Proxmox, and how Docker Engine and its containers run within some of these VMs. This layered structure allows for more efficient resource utilization and simplified management.
Comparison: When is Which More Suitable? (Or Both?)
The decision to use Proxmox and Docker separately or together depends on your needs and homelab goals. Each has its unique advantages and disadvantages.
Proxmox Alone:
- Advantages: Running different operating systems (Windows, various Linux distributions), hardware-level isolation, easy backup and snapshotting, ability to assign dedicated resources (CPU, RAM) to VMs. Ideal for running older hardware or services that require specific hardware passthrough.
- Disadvantages: Higher resource consumption due to each VM having its own operating system overhead, longer boot times. You need to perform individual installations within the VM to manage application dependencies.
- When to choose: If you need different operating systems (e.g., a Windows Active Directory server and several Linux servers), or if an application requires direct access to a specific hardware card (like GPU passthrough), Proxmox is indispensable as a standalone or primary layer.
Docker Alone (on Physical Server):
- Advantages: Very lightweight and fast, easily manages application dependencies, portability, fast deployment and rollback. You can run hundreds of applications on a single operating system.
- Disadvantages: Can only run Linux-based containers (Windows containers exist but generally don’t run on a Linux host), does not provide operating system-level isolation. This means all containers share the same kernel. A kernel-level security vulnerability in one container could affect others.
- When to choose: If you only want to run Linux-based applications on a single Linux operating system and don’t need hardware virtualization, you can install a Linux distribution directly on the physical server and then install Docker on top of it. This is a method I use for some lightweight services.
Proxmox and Docker Together (Recommended Homelab Approach):
- Advantages: The best of both worlds. Hardware-level flexibility and isolation (Proxmox), application-level flexibility and isolation (Docker). More efficient resource utilization. Easy management and automation.
- Disadvantages: Having two separate layers to manage can seem a bit more complex initially. However, this complexity is negligible compared to the flexibility it provides.
- When to choose: This is the most logical and flexible approach for most homelab users. Isolating different services in different VMs, and then isolating applications with Docker within those VMs, provides significant advantages in terms of both security and ease of management. For example, you can dedicate one VM solely for web services and run reverse proxies like Nginx, Caddy with Docker inside it, while dedicating another VM for databases and running PostgreSQL or Redis inside Docker.
A Practical Homelab Setup Example and My Approach
When starting a homelab setup, the path I usually follow is as follows:
-
Proxmox Installation on Physical Server: The first step is to install Proxmox VE on my physical server. During installation, I pay attention to disk configuration. I usually use a small SSD for the operating system, a larger, faster disk (NVMe or SSD) for VMs and containers, and an HDD pool for archives/backups. After installation, I access the Proxmox web interface and configure basic settings (network, storage).
-
Creating a Base Linux VM: I typically create one or two “main” Linux virtual machines (VMs). My preference is usually Debian or Ubuntu Server LTS versions. When creating these VMs from the Proxmox interface, I allocate sufficient CPU cores (2-4), RAM (4-8 GB), and disk space (50-100 GB). These VMs will be the “hosts” where I will later run the Docker Engine. For example, I have a VM named “backend-vm.”
-
Installing Docker Engine Inside the VM: I connect to the created Linux VM via SSH and install the Docker Engine by following the standard steps.
# Docker installation on Ubuntu/Debian sudo apt update sudo apt install ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg echo \ "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \ "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo usermod -aG docker $USER # Add your user to the docker groupAfter completing these steps, I restart the VM and check if Docker is running with the
docker run hello-worldcommand. -
Deploying Applications with Docker Compose: Now, Docker is ready to run inside my Linux VM. I manage my applications (Nginx, PostgreSQL, Redis, my custom services) with Docker Compose files. For example, I use a simple
docker-compose.yamlfile for my blog site’s backend and database.# A simple docker-compose.yaml example version: '3.8' services: web: image: my-blog-app:latest ports: - "8000:8000" depends_on: - db environment: DATABASE_URL: postgresql://user:password@db:5432/mydb db: image: postgres:14 environment: POSTGRES_DB: mydb POSTGRES_USER: user POSTGRES_PASSWORD: password volumes: - db_data:/var/lib/postgresql/data volumes: db_data:I place this file inside the VM and bring up all services with a single command:
docker compose up -d.
This layered approach provides me with flexibility. Let’s say one day the disk space on “backend-vm” becomes insufficient or its performance drops. I can allocate more disk or CPU/RAM to that VM from the Proxmox interface. Or I can create a completely new VM and migrate my Docker Compose stack there. This transition is much faster and safer than reinstalling the physical server or reconfiguring all applications one by one.
Common Mistakes and My Lessons Learned
In my homelab journey, I made many mistakes on both the Proxmox and Docker sides, but I learned valuable lessons from each.
-
Proxmox Disk Space Management: Initially, I partitioned the disks I installed on Proxmox very simply. For example, I would create a single large LVM-thin pool and stack all VMs there. However, over time, this led to performance bottlenecks. Especially for I/O-intensive services like databases, other VMs in the same pool could cause problems. Now, I use separate storage for the operating system, SSD-based separate storage for VMs, and HDD-based different storage for backups in Proxmox. For critical VMs, I even try to optimize performance by creating disks in
rawformat instead of direct LVM-thin. A few years ago, I noticed my Redis cache slowing down and realized it was due to another heavily working VM in the same disk pool. Moving that VM to a separate disk increased Redis performance by 40%. -
Docker Container Network Isolation: Docker containers can communicate with each other over the default
bridgenetwork. However, sometimes this is not sufficient or can pose security risks. For example, you might want to isolate a database container so that only a specific application container can access it. Initially, I put all containers on a single network, but a security audit revealed this to be risky. Now, I define a separate Docker network for each application stack.# Defining a custom network with Docker Compose version: '3.8' services: web: image: my-app:latest networks: - app_network db: image: postgres:14 networks: - app_network networks: app_network: driver: bridge # You can also specify an IP range if desired # ipam: # config: # - subnet: 172.20.0.0/24This ensures that
webanddbservices communicate only overapp_networkand cannot directly communicate with containers on other Docker networks. -
Resource Limits and OOM-Killed Issues: I initially neglected to define resource limits (CPU, RAM) for Docker containers. Especially in the backend of my own side products, during a development phase with a memory leak, a container could consume all of the VM’s RAM and become
OOM-killed. This also affected other running services. Now, I make it a habit to defineresources.limitsandresources.reservationsfor every critical container.# Setting resource limits with Docker Compose version: '3.8' services: my_service: image: my-image:latest deploy: resources: limits: memory: 512M # Can use a maximum of 512MB RAM cpus: '0.5' # Can use a maximum of 0.5 CPU cores reservations: memory: 128M # At least 128MB RAM is always reservedThese limits prevent a container from spiraling out of control and affecting the entire system, increasing overall system stability. Last month, a reporting service processed much more data than expected, exceeded its RAM limit, and was OOM-killed. Thanks to the limits, my other services continued to run; only the reporting service stopped and I could easily restart it.
Conclusion: The Right Perspective When Starting a Homelab Journey
When embarking on a homelab journey, the question “Proxmox or Docker?” is actually a reflection of the question “how should I partition my physical hardware and how should I isolate my applications?”. My clear position is this: these two technologies are not rivals; on the contrary, they are complementary layers, and using them together provides the most efficient solution in most homelab scenarios.
If you have a single physical server, starting with Proxmox to partition your hardware into virtual machines or LXCs will provide you with the highest flexibility and isolation. Then, by installing Docker Engine inside these virtual machines, you can isolate, easily deploy, and manage your applications as containers. This layered approach meets your need to run different operating systems and modernizes your application development and deployment processes.
Remember, in the world of technology, “either/or” is often a false dilemma. The important thing is to understand what each tool does and to create the most appropriate combination for your needs. This hybrid structure has provided me with great benefits for years in my homelab and many work environments. In the next step, we can discuss how to make your Proxmox-Docker homelab more secure or how to scale it with Kubernetes.