Why Debian 12 for Docker
Debian is what Ubuntu is built on, but without the extras. No snap packages, no Ubuntu Pro nag screens, no Canonical telemetry, no systemd-resolved stub resolver causing DNS headaches in containers. It’s a leaner, more predictable base for a Docker host, and there’s a reason it’s the default choice for most serious self-hosting deployments.
From the homelab: Debian is my go-to server OS for anything that needs to be rock-solid. Most of my Proxmox LXC containers run Debian, and Docker on Debian just works once it is set up correctly.
I run Debian 12 on most of my Proxmox VMs that serve as Docker hosts. Proxmox itself is Debian-based, so if you’re running Proxmox and creating VMs or LXC containers for Docker workloads, Debian 12 keeps your entire stack on the same foundation. No surprises when you’re troubleshooting at 2am.
This guide covers installing Docker Engine from Docker’s official repository on Debian 12 (Bookworm), the post-install configuration you shouldn’t skip, and the specific differences from our Ubuntu 24.04 Docker guide. If you’re coming from Ubuntu, I’ll call out where things differ so you’re not caught off guard.

Why Not Ubuntu?
Ubuntu is perfectly fine for Docker. I have an entire guide on it. But Debian has specific advantages for a dedicated Docker host:
- No snap. Ubuntu’s push towards snap packages adds complexity and resource overhead. Docker via snap is particularly problematic, with sandboxing that breaks volume mounts and networking. Debian doesn’t have snap at all.
- Lighter footprint. A minimal Debian 12 server install uses less RAM and disk than Ubuntu Server. On a VM where you’re allocating resources deliberately, that matters.
- No systemd-resolved stub. Ubuntu’s DNS stub resolver on
127.0.0.53is the single most common cause of DNS issues inside Docker containers. Debian doesn’t enable this by default, so DNS just works out of the box. - Longer track record for stability. Debian’s release cycle is slower and more conservative. Packages are older but thoroughly tested. For a Docker host where you want the platform to be boring and reliable, this is a feature.
- Proxmox alignment. If your hypervisor is Proxmox, your VMs being Debian means one set of knowledge, one set of package management patterns, one set of troubleshooting skills.
The trade-off is that Debian’s base packages are older than Ubuntu’s. The kernel, systemd, and other system components will be behind Ubuntu LTS. For a Docker host this rarely matters because your workloads run inside containers with their own dependencies. The host OS just needs to run Docker reliably, and Debian excels at that.
Prerequisites
- A machine running Debian 12 (Bookworm), either bare metal, VM, or LXC container
- Root access or a user with sudo privileges
- A working internet connection
- At least 2 GB RAM and 20 GB disk space
If you’re running Docker inside a Proxmox LXC container rather than a VM, you need to enable specific container features. In the Proxmox web UI, go to the container’s Options > Features and enable keyctl and nesting. Without these, Docker won’t be able to manage its own containers inside the LXC. Some people also need to enable fuse depending on their storage driver. VMs don’t have this issue.
Step 1: Remove Debian’s Default Docker Packages
Debian 12 ships docker.io in its default repositories. This is an older, Debian-maintained build of Docker that lags behind the official releases. Remove it, even if you don’t think it’s installed:
sudo apt remove docker docker.io containerd runc 2>/dev/null
sudo apt autoremove -y
Unlike Ubuntu, you don’t need to worry about removing snap packages here. Debian doesn’t ship snap.
Step 2: Install Prerequisites
sudo apt update
sudo apt install -y ca-certificates curl gnupg
These may already be installed on a Debian 12 system, but it’s worth running to be sure. The gnupg package is needed for verifying Docker’s repository signing key.
Step 3: Add Docker’s Official Repository
This is where the process diverges from Ubuntu. The repository URL uses debian instead of ubuntu, and the codename will be bookworm.
Add Docker’s GPG key
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
Add the repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "${VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Update the package index:
sudo apt update
You should see download.docker.com appear in the apt output. If the codename detection doesn’t work (rare, but possible on minimal installs), you can hardcode bookworm in place of the $(. /etc/os-release && echo "${VERSION_CODENAME}") substitution.
Step 4: Install Docker Engine
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
This installs the same set of packages as on Ubuntu:
- docker-ce – Docker Engine daemon
- docker-ce-cli – The
dockercommand-line tool - containerd.io – The container runtime
- docker-buildx-plugin – Extended build capabilities
- docker-compose-plugin – Docker Compose v2 as
docker compose
Step 5: Verify the Installation
sudo systemctl status docker
Look for Active: active (running). Then test with hello-world:
sudo docker run hello-world
If you see the “Hello from Docker!” message, the installation is complete. Check your versions:
docker version
docker compose version
Post-Install Configuration
These steps apply regardless of which Linux distro you’re running Docker on, but I’ll note where Debian behaves differently from Ubuntu.
Add your user to the docker group
sudo usermod -aG docker $USER
Log out and back in, then test without sudo:
docker run hello-world
On a fresh Debian 12 install, your user might not have sudo access by default. If sudo isn’t found or your user isn’t in the sudoers file, log in as root and run: apt install sudo && usermod -aG sudo yourusername. Then log back in as your user. This is a Debian-specific gotcha that Ubuntu users won’t expect, since Ubuntu configures sudo during installation.
Enable Docker on boot
sudo systemctl enable docker.service
sudo systemctl enable containerd.service
Configure log rotation
This is critical on any Docker host. Without it, container logs grow without limit and will eventually fill your disk. I’ve seen it happen on production servers, and it’s always at the worst possible time.
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json > /dev/null <<'EOF'
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2"
}
EOF
sudo systemctl restart docker
This caps each container’s log at 10 MB with 3 rotated files. Adjust to suit your disk space.
Configure DNS (usually not needed on Debian)
This is where Debian shines compared to Ubuntu. On Ubuntu, you almost always need to add explicit DNS servers to daemon.json because systemd-resolved listens on 127.0.0.53, which is unreachable from inside containers.
Debian 12 doesn’t enable the stub resolver by default. Your containers will inherit the host’s DNS settings from /etc/resolv.conf, and those settings will typically point to your network’s actual DNS server, not a loopback address. DNS inside containers just works.
If you do experience DNS issues (unlikely but possible depending on your network configuration), add DNS servers to your daemon.json:
{
"dns": ["1.1.1.1", "8.8.8.8"]
}
If you run your own DNS server (Pi-hole, AdGuard Home), point Docker at that instead of public resolvers. That way your containers benefit from the same ad blocking and local DNS resolution as the rest of your network.
Differences from the Ubuntu Guide
If you’ve already followed the Ubuntu 24.04 guide and are now setting up a Debian host, here’s a quick reference of what’s different:
| Aspect | Ubuntu 24.04 | Debian 12 |
|---|---|---|
| Snap removal | May need sudo snap remove docker |
Not applicable, no snap |
| Repository URL | download.docker.com/linux/ubuntu |
download.docker.com/linux/debian |
| Codename | noble |
bookworm |
| DNS in containers | Often broken due to systemd-resolved stub | Works out of the box |
| sudo access | Configured during install | May need manual setup |
| Base footprint | ~1.2 GB RAM idle | ~400-600 MB RAM idle |
For Proxmox Users
If you’re running Proxmox and creating Docker hosts, Debian 12 is the natural choice since Proxmox itself is Debian-based. Here are some specific considerations:
VM vs LXC for Docker
Both work, but VMs are simpler. Docker in an LXC container requires the keyctl and nesting features enabled, and some storage backends can be problematic. If you’re not constrained on resources, a VM avoids these issues entirely.
For an LXC container, use a privileged container or ensure the unprivileged container has the right feature flags. In the Proxmox UI: Container > Options > Features > check keyctl, nesting, and optionally fuse.
Recommended VM sizing for Docker
- Light use (1-5 containers): 2 CPU cores, 2 GB RAM, 32 GB disk
- Medium use (5-15 containers): 4 CPU cores, 4 GB RAM, 64 GB disk
- Heavy use (15+ containers): 4-8 CPU cores, 8 GB RAM, 100+ GB disk
Use virtio for both disk and network interfaces in Proxmox. The performance difference over IDE or E1000 emulation is significant, particularly for the I/O patterns Docker generates.
Create a Debian 12 VM template in Proxmox with Docker pre-installed. Then you can clone new Docker hosts in seconds. I have a template called “debian12-docker” that I clone whenever I need a new host. It has Docker installed, log rotation configured, and my SSH key already deployed. A new Docker host goes from zero to running containers in under two minutes.
Firewall Configuration
Debian 12 doesn’t ship with a firewall enabled by default, which means all your container ports are exposed to your network. If this Docker host is accessible from the internet, or even from an untrusted network segment, configure a firewall.
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw enable
Docker modifies iptables directly and bypasses UFW rules by default. This means a container publishing port 8080 will be reachable even if UFW doesn’t allow port 8080. This is a well-documented issue. The simplest mitigation is to bind container ports to 127.0.0.1 (e.g., -p 127.0.0.1:8080:80) and use a reverse proxy like Nginx to control external access. Alternatively, set "iptables": false in daemon.json, but be aware this breaks container-to-internet networking unless you add your own iptables rules.
Unattended Security Updates
For a server that runs continuously, enable automatic security updates so you’re not manually patching every Debian host in your fleet:
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
This configures Debian to automatically install security patches. It won’t upgrade Docker itself (that comes from Docker’s repo, not Debian’s), but it keeps the base OS patched without intervention.
Debian is the dominant Linux distribution in enterprise server environments and the foundation for most container-optimised operating systems. If you’re building infrastructure skills for your career, being comfortable with Debian gives you a broader base than knowing only Ubuntu. The differences are subtle but they come up in interviews: “Why would you choose Debian over Ubuntu for a server?” is a question I’ve been asked twice. Having an answer that references resource overhead, DNS behaviour, and release stability demonstrates real operational experience.
Key Takeaways
- Debian 12 is a lighter, more predictable Docker host than Ubuntu, with no snap, no DNS stub resolver issues, and a smaller resource footprint
- The installation process is nearly identical to Ubuntu, with
debianreplacingubuntuin the repository URL andbookwormas the codename - Always install from Docker’s official repository, never from Debian’s default
docker.iopackage - DNS inside containers works out of the box on Debian, unlike Ubuntu where you often need to configure
daemon.json - Proxmox users should prefer Debian 12 for Docker VMs to keep the entire stack on the same distribution
- For Docker in Proxmox LXC containers, enable
keyctlandnestingfeatures - Configure log rotation immediately and be aware that Docker bypasses UFW firewall rules by default
- Create a Proxmox VM template with Docker pre-installed to spin up new hosts in minutes
Related Guides
If you found this useful, these guides continue the journey:
- Essential Docker Commands You Need to Know — The core Docker commands every homelab operator should know by heart
- Docker Compose Beginner’s Guide — Learn to manage multi-container applications with Docker Compose
- How to Install Docker on Ubuntu 24.04 — Step-by-step Docker installation on Ubuntu 24.04 LTS
- How to Install Docker on Raspberry Pi — Get Docker running on ARM-based Raspberry Pi hardware
- How to Build Your First Homelab in 2026 — Everything you need to plan and build a homelab from scratch

ReadTheManual is run, written and curated by Eric Lonsdale.
Eric has over 20 years of professional experience in IT infrastructure, cloud architecture, and cybersecurity, but started with PCs long before that.
He built his first machine from parts bought off tables at the local college campus, hoping they worked. He learned on BBC Micros and Atari units in the early 90s, and has built almost every PC he’s used between 1995 and now.
From helpdesk to infrastructure architect, Eric has worked across enterprise datacentres, Azure environments, and security operations. He’s managed teams, trained engineers, and spent two decades solving the problems this site teaches you to solve.
ReadTheManual exists because Eric believes the best way to learn IT is to build things, break things, and actually read the manual. Every guide on this site runs on infrastructure he owns and maintains.
Enjoyed this guide?
New articles on Linux, homelab, cloud, and automation every 2 days. No spam, unsubscribe anytime.

