Using an unprivileged LXC container is the recommended method. It’s incredibly lightweight, fast to boot, and provides strong security by mapping the container’s root user to a non-privileged user on the Proxmox host. We will use a Debian template, as it’s the foundation of Proxmox and is very resource-efficient.

Step 1: Create the Unprivileged LXC Container#

  1. Download a Template: In your Proxmox web UI, select your node, then go to CT Templates under your local storage (or any other storage you use for templates). Click Templates and download the latest Debian template (e.g., `debian-12-standard).

  2. Create the Container: Click the Create CT button in the top-right corner.

    • General: Give it a Hostname (e.g., docker-host) and set a secure Password. Uncheck Unprivileged container for now—we will make it unprivileged in the configuration file, but you must enable specific features first. Alternatively, if you leave it unprivileged, you must edit the config file manually later.

    • Template: Select the Debian template you just downloaded.

    • Disks: Set a disk size. 8GB is a minimum, but 20-30GB is safer depending on how many Docker images you plan to store.

    • CPU: Allocate CPU cores (e.g., 2).

    • Memory: Allocate RAM (e.g., 1024MB or 2048MB).

    • Network: Configure your network settings as needed (DHCP or static).

    • DNS: Leave as default unless you have specific needs.

    • Confirm: Review the settings and click Finish.

  3. Enable Nesting & Keyctl: Do not start the container yet.

    • Find your new container in the server view (e.g., 101 (docker-host)).

    • Go to the Options tab.

    • Find Features and double-click it (or select it and click Edit).

    • Check the boxes for Nesting and Keyctl.

    • Click OK.

    Why?

    • Nesting: Allows the container to run its own virtualization/containerization, which is what Docker is.

    • Keyctl: Allows the container to manage kernel keyrings, a feature Docker requires.


Step 2: Install Docker in the Container#

  1. Start and Access the Container: Start your new LXC container and open its Console.

  2. Update the System: Log in as root with the password you set. First, update all packages:

    apt update
    apt upgrade -y
    
  3. Install Docker: We will use the official Docker convenience script. This is the simplest way to get the latest version of Docker CE.

    curl -fsSL https://get.docker.com -o get-docker.sh
    sh get-docker.sh
    

    This script automatically detects your OS, adds the official Docker repository, and installs Docker.

  4. Add Your User to the Docker Group (Optional but Recommended): If you plan to use a non-root user inside the container, create one and add it to the docker group so you don’t have to type sudo for every Docker command.

    # (If you need to create a new user first)
    # adduser myuser
    
    # (Add the user to the docker group)
    usermod -aG docker myuser 
    

Step 3: Check Storage Driver (Important!)#

If your Proxmox host uses ZFS for storage (very common), Docker’s default overlay2 storage driver may not work correctly and will fall back to the slow and inefficient vfs driver. This can lead to poor performance and rapidly growing disk usage.

  1. Check Your Storage Driver: Run the following command inside the LXC container:

    docker info | grep "Storage Driver"
    
  2. Analyze the Output:

    • ✅ If you see Storage Driver: overlay2, you are all set! Newer Proxmox/Docker versions often handle this correctly.

    • ⚠️ If you see Storage Driver: vfs, you must fix it. The easiest way is to use fuse-overlayfs.

  3. Fixing vfs with fuse-overlayfs:

    • Install the fuse-overlayfs package inside the LXC:

      apt install -y fuse-overlayfs
      
    • Restart the Docker service:

      systemctl restart docker
      
    • Verify the fix. Run the check again:

      docker info | grep "Storage Driver"
      
    • It should now show overlay2.


Step 4: Verify the Installation#

Now for the moment of truth. Run the “hello-world” container:

docker run hello-world

You should see a message starting with “Hello from Docker!” This confirms that Docker is installed and working correctly.


🚨 Troubleshooting: AppArmor Permission Denied#

If your docker run hello-world command fails with an AppArmor or permission denied error, it’s a common issue with nested containers.

The Fix: You need to tell Proxmox to disable the AppArmor profile for this specific container, giving it more permissions.

  1. On the Proxmox Host (not in the LXC): Open a shell on your Proxmox host (either via SSH or the “Shell” in the node’s GUI).

  2. Edit the Container’s Config File: Use nano to edit the container’s configuration. Replace 101 with your container’s ID.

    nano /etc/pve/lxc/101.conf
    
  3. Add the Unconfined Line: Add the following line to the bottom of the file:

    lxc.apparmor.profile: unconfined
    
  4. Save and Exit: Press CTRL+O to save, Enter to confirm, and CTRL+X to exit.

  5. Reboot the Container: Stop and start the LXC container from the Proxmox UI for the change to take effect.

Try running docker run hello-world inside the container again. It should now work.

You are all set! You now have a fast, lightweight, and secure Docker environment running inside a Proxmox LXC container.