Prerequisites
System requirements and assumptions for this guide.
- Ubuntu 24.04 LTS with ZFS support
- Root access or sudo privileges
- Two identical disks for the mirror (e.g.,
/dev/sdband/dev/sdc) - ZFS encryption key directory set up at
/etc/zfs/keys/
This guide creates a dedicated encrypted ZFS mirror pool named zcontainer specifically for Docker containers and
images, providing complete isolation from the system pool.
Install Docker Engine
Follow the official Docker installation guide for Ubuntu to install Docker Engine using the apt repository method.
After installation, add your user to the docker group:
sudo usermod -aG docker $USER
Log out and back in for group membership to take effect.
Create Dedicated ZFS Pool for Docker
Create a dedicated encrypted ZFS mirror pool optimized for Docker workloads.
This guide uses the same encryption key as your root pool (/etc/zfs/keys/zroot.key) for consistency and simplified
key management.
Identify Container Disks
Identify the two disks you’ll use for the mirror using persistent disk-by-id paths:
# List available disks with their by-id paths
ls -lh /dev/disk/by-id/ | grep -v part
# Set your disk paths (replace with your actual disk IDs)
export CONTAINER_DISK1=/dev/disk/by-id/ata-Samsung_SSD_870_EVO_1TB_XXXXXXXXXXXXX
export CONTAINER_DISK2=/dev/disk/by-id/ata-Samsung_SSD_870_EVO_1TB_YYYYYYYYYYYYY
Warning: The disks will be completely wiped. Verify you’re using the correct disks before proceeding.
Stop Docker Service
If Docker is already installed, stop it before creating the pool:
sudo systemctl stop docker
sudo systemctl stop containerd
Create ZFS Mirror Pool
Create the encrypted mirror pool with optimized settings:
sudo zpool create -f \
-m none \
-O acltype=posixacl \
-o ashift=12 \
-O atime=off \
-o autotrim=on \
-o cachefile=none \
-O canmount=off \
-O compression=zstd \
-O dnodesize=auto \
-O encryption=aes-256-gcm \
-O keyformat=passphrase \
-O keylocation=file:///etc/zfs/keys/zroot.key \
-O normalization=formD \
-O relatime=off \
-O xattr=sa \
zcontainer mirror ${CONTAINER_DISK1} ${CONTAINER_DISK2}
Create Docker Dataset
Create the dataset that Docker will use:
sudo zfs create \
-o mountpoint=/var/lib/docker \
-o recordsize=128K \
zcontainer/DOCKER
Verify Pool Creation
# Check pool status
sudo zpool status zcontainer
# Check pool properties
sudo zpool get all zcontainer
# Check dataset properties
sudo zfs get all zcontainer/DOCKER
# Verify mountpoint
mount | grep docker
Expected output for mountpoint: zcontainer/DOCKER on /var/lib/docker type zfs (rw,...)
Configure Docker Daemon
Configure Docker daemon with ZFS storage driver and logging.
Create Docker Daemon Configuration
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json > /dev/null << 'EOF'
{
"storage-driver": "zfs",
"storage-opts": [
"zfs.fsname=zcontainer/DOCKER"
],
"log-driver": "journald",
"log-opts": {
"tag": "{{.Name}}"
}
}
EOF
Configuration breakdown:
Storage Driver:
storage-driver: zfs- Use native ZFS storage driver instead of overlay2zfs.fsname=zcontainer/DOCKER- ZFS dataset for container storage
Logging:
log-driver: journald- Send container logs to systemd journaltag: {{.Name}}- Tag journal entries with container name for easy filtering
Benefits of this configuration:
- Dedicated pool isolates Docker from system storage
- Native ZFS snapshots for containers and images
- Full encryption at rest (AES-256-GCM)
- Transparent compression (ZSTD) reduces storage usage
- Mirror redundancy protects against disk failure
- No overlay filesystem overhead
- Copy-on-write efficiency for container layers
- Easy backup via ZFS send/receive
Start Docker Service
sudo systemctl daemon-reload
sudo systemctl enable --now docker
sudo systemctl enable --now containerd
Verify Installation
Validate Docker installation and ZFS integration.
Check Docker Service Status
sudo systemctl status docker
Should show: Active: active (running)
Verify ZFS Storage Driver
docker info | grep -A 10 "Storage Driver"
Expected output:
Storage Driver: zfs
ZFS Dataset: zcontainer/DOCKER
Parent Dataset: zcontainer/DOCKER
ZFS Filesystem: zcontainer/DOCKER