Docker gives you the flexibility to run Home Assistant alongside other services on the same machine. But it also means more decisions upfront. Here's how to get it right when starting fresh or moving an existing setup into containers.
Docker is great when Home Assistant is not the only thing on your server. If it is, you're probably better off with Home Assistant OS. Here's a quick decision guide.
The honest truth: About 70% of Home Assistant users are better off with HA OS. Docker adds complexity that only pays off if you actually need to share that machine with other services. If you're reading this page because someone told you Docker is "the pro way," think about what problem you're actually solving first.
Home Assistant comes in four flavors. Two use Docker directly (Container and Supervised), and two don't require you to touch Docker at all (OS and Core).
The full package. Runs its own minimal Linux OS with Docker under the hood (you never touch it). Includes the Supervisor for add-ons, automatic backups, and managed updates.
Best for: Dedicated hardware (Pi, NUC, mini PC). Most users.
Just the Home Assistant core app in a single Docker container. You manage everything: Docker Compose config, companion services, updates, backups. No Supervisor, no add-on store.
Best for: NAS users, existing Docker setups, people who want full control.
Runs the Supervisor on top of your own Linux install (Debian 13 required). You get add-ons and managed updates while keeping control of the host OS. Fragile if you deviate from the requirements.
Best for: Advanced users who need add-ons AND host OS access.
Installed directly in a Python virtual environment. No Docker involved. You manage Python dependencies, system packages, and everything else. Rarely the right choice anymore.
Best for: Developers contributing to HA core. That's about it.
This gets Home Assistant Container running in about 10 minutes. You'll need Docker and Docker Compose already installed on your machine.
mkdir -p ~/homeassistant
cd ~/homeassistantservices:
homeassistant:
container_name: homeassistant
image: ghcr.io/home-assistant/home-assistant:stable
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
restart: unless-stopped
network_mode: hostWhy network_mode: host? Home Assistant uses mDNS to discover devices on your network. Bridge networking blocks this. Host mode lets HA see everything on your LAN, which is what you want for auto-discovery of lights, speakers, and other smart devices.
docker compose up -dGive it a minute to download and start up. Then open http://your-server-ip:8123 in your browser. You'll see the onboarding wizard to create your first user account.
docker compose logs -f homeassistantWatch the logs scroll by. Once you see "Setup of domain homeassistant took X seconds," you're good. Press Ctrl+C to exit the log view.
This trips up more people than anything else in Docker-based HA setups.
Bottom line: Use host mode unless you have a specific reason not to. The most common reason for bridge mode is running a reverse proxy (like Nginx or Traefik) to put HA behind HTTPS on port 443. In that case, use bridge mode with port 8123 mapped, and configure your proxy to forward traffic to it. Check our remote access guide for the full setup.
Zigbee coordinators, Z-Wave sticks, and Bluetooth adapters all connect via USB. Docker containers can't see them unless you explicitly pass them through.
# List USB serial devices
ls -la /dev/serial/by-id/
# Example output:
# usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus-if00-port0 -> ../../ttyUSB0Always use the /dev/serial/by-id/ path, not /dev/ttyUSB0. The by-id path stays the same even if you plug in additional USB devices. The numbered path can shift around.
services:
homeassistant:
container_name: homeassistant
image: ghcr.io/home-assistant/home-assistant:stable
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
devices:
- /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0-if00-port0:/dev/ttyUSB0
restart: unless-stopped
network_mode: hostAfter changing the compose file, recreate the container: docker compose up -d. The device will be available inside the container at the path you mapped it to. For more on Zigbee, see our Zigbee guide.
Without the add-on store, you run these services as separate Docker containers. Here's a production-ready compose file with the most common ones.
services:
homeassistant:
container_name: homeassistant
image: ghcr.io/home-assistant/home-assistant:stable
volumes:
- ./ha-config:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
devices:
- /dev/serial/by-id/your-zigbee-dongle:/dev/ttyUSB0
depends_on:
- mosquitto
restart: unless-stopped
network_mode: host
mosquitto:
container_name: mosquitto
image: eclipse-mosquitto:2
volumes:
- ./mosquitto/config:/mosquitto/config
- ./mosquitto/data:/mosquitto/data
- ./mosquitto/log:/mosquitto/log
ports:
- "1883:1883"
restart: unless-stopped
zigbee2mqtt:
container_name: zigbee2mqtt
image: koenkk/zigbee2mqtt
volumes:
- ./zigbee2mqtt-data:/app/data
- /run/udev:/run/udev:ro
devices:
- /dev/serial/by-id/your-zigbee-dongle:/dev/ttyACM0
ports:
- "8080:8080"
depends_on:
- mosquitto
restart: unless-stopped
esphome:
container_name: esphome
image: ghcr.io/esphome/esphome
volumes:
- ./esphome-config:/config
network_mode: host
restart: unless-stoppedNote: If you use Zigbee2MQTT, pass the Zigbee dongle to the Z2M container instead of Home Assistant. Only one process can access a serial device at a time. For more on these services, check our guides on MQTT, Zigbee, and ESPHome.
MQTT broker. Required for Zigbee2MQTT, Tasmota devices, and many automations. Lightweight, runs on any hardware.
Bridges your Zigbee devices to MQTT. Supports 4,000+ devices with a web UI for management. Alternative to ZHA.
Program ESP32/ESP8266 boards for custom sensors and devices. Great for DIY projects.
Visual flow-based automation tool. Image: nodered/node-red. Port 1880. Good for complex multi-step automations.
AI-powered NVR for security cameras. Needs a Coral TPU for real-time detection. Port 5000. See our camera guide.
Long-term data storage and beautiful charts. Great for energy monitoring and historical trends.
Without the Supervisor, you don't get automatic backups. Set this up now, before you have 50 automations and a dozen integrations you'd hate to rebuild from scratch.
#!/bin/bash
# backup-ha.sh
BACKUP_DIR="/backups/homeassistant"
DATE=$(date +%Y-%m-%d_%H%M)
mkdir -p "$BACKUP_DIR"
# Stop HA to ensure consistent backup
docker compose stop homeassistant
# Create compressed archive
tar -czf "$BACKUP_DIR/ha-backup-$DATE.tar.gz" \
./config ./zigbee2mqtt-data ./mosquitto \
docker-compose.yml
# Restart
docker compose up -d
# Keep last 7 backups
ls -t "$BACKUP_DIR"/ha-backup-*.tar.gz | tail -n +8 | xargs rm -f
echo "Backup complete: ha-backup-$DATE.tar.gz"Add this to cron with crontab -e and add 0 3 * * * /path/to/backup-ha.sh to run it daily at 3 AM. For offsite backups, add an rclone sync line to push to Google Drive or a remote server.
The SSD rule: If you're running Home Assistant on an SD card, stop. SD cards were not designed for the constant read/write that HA does to its SQLite database. They will fail, usually within 3 to 12 months. Use an SSD. Even a cheap one will outlast any SD card by years. Your backups are useless if the card dies between backups.
Updates are straightforward. Just pull the new image and recreate. Your config survives because it lives in a mounted volume.
# 1. Check the release notes first
# https://www.home-assistant.io/blog/categories/release-notes/
# 2. Create a backup
./backup-ha.sh
# 3. Pull the new image
docker compose pull
# 4. Recreate the container with the new image
docker compose up -d
# 5. Check the logs for errors
docker compose logs -f homeassistantservices:
watchtower:
container_name: watchtower
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_SCHEDULE=0 0 4 * * *
restart: unless-stoppedFair warning: Watchtower updates all your containers automatically. Home Assistant releases occasionally include breaking changes that require manual config updates. Many experienced users prefer manual updates so they can read the release notes first and test in advance. If you do use Watchtower, at least monitor the HA changelog.
# Pin to a specific version in docker-compose.yml:
image: ghcr.io/home-assistant/home-assistant:2026.2.0
# Then recreate:
docker compose up -dYou can pin any version. Check available tags on the GitHub releases page. Restoring from your backup after downgrading is the safest approach since the database schema sometimes changes between versions.
A few things that make a real difference in day-to-day performance.
Home Assistant writes to its database constantly. SSDs handle this without breaking a sweat. SD cards degrade fast under write-heavy workloads. A $20 SSD will save you from data loss headaches.
By default, HA keeps 10 days of history. That database can grow to several gigabytes. In configuration.yaml, set recorder: purge_keep_days: 5 and exclude entities you don't need history for. If you want long-term data, offload it to InfluxDB.
Home Assistant itself needs about 512MB to 1GB of RAM. Add more for each companion container: Zigbee2MQTT uses 100-200MB, Frigate can use 2-4GB depending on camera count. Monitor with docker stats.
Instead of :stable or :latest, pin a specific version like :2026.2.0. This prevents surprise updates when you recreate a container and makes rollbacks trivial.
Your hardware needs depend on how many containers you plan to run. Here are three tiers that cover most situations.
Raspberry Pi 4 (4GB)
+ SSD via USB 3.0 adapter
HA + Mosquitto + Z2M. Handles 50-100 devices. About $60-80 total.
Intel N100 mini PC (8-16GB)
+ NVMe SSD
Full stack including Frigate. Low power (10-15W). Future-proof. About $120-180.
Synology / Unraid / TrueNAS
or any x86 server
Already have one? Run HA alongside your existing services. Perfect Docker use case.
Already running HA OS and want to switch to Docker? Or going the other direction? Here's what to expect.
The backup restores your automations, integrations, dashboards, and entity history. Add-ons don't transfer, so plan to set up Mosquitto, Z2M, and other services as separate containers.
Same process in reverse. Create a backup from the Docker instance, install HA OS on your target hardware, and restore during onboarding. The HA OS onboarding wizard has a "Restore from backup" option on the first screen. Moving to HA OS is generally easier since you gain the add-on store instead of losing it.
Running Docker or HA OS? Our free scan tells you which of your existing devices work with Home Assistant and what to expect during migration.
Scan Your Devices FreeTakes about 2 minutes. No account needed.