Эта статья — не пересказ документации Docker на 800 страниц. Это конкретное руководство: как поставить Docker на домашний сервер, как запустить первые контейнеры, как описать инфраструктуру умного дома в одном файле и как не потерять данные при обновлении. Минимум теории, максимум практики.
-v /opt/mosquitto/config:/mosquitto/config — директория /opt/mosquitto/config на хосте доступна внутри контейнера как /mosquitto/config. Всё, что контейнер пишет в /mosquitto/config, на самом деле сохраняется на хосте. Удалили контейнер, создали заново — данные на месте.
Многие контейнеры настраиваются через переменные окружения:
bashdocker run -d --name influxdb \
-p 8086:8086 \
-e DOCKER_INFLUXDB_INIT_MODE=setup \
-e DOCKER_INFLUXDB_INIT_USERNAME=admin \
-e DOCKER_INFLUXDB_INIT_PASSWORD=supersecret \
-e DOCKER_INFLUXDB_INIT_ORG=home \
-e DOCKER_INFLUXDB_INIT_BUCKET=homeassistant \
-v /opt/influxdb/data:/var/lib/influxdb2 \
influxdb:2-e задаёт переменную. Какие переменные поддерживает конкретный образ — описано в его документации на Docker Hub или GitHub.
bashdocker run -d --name mosquitto --restart unless-stopped eclipse-mosquitto:2--restart unless-stopped — контейнер перезапускается автоматически при падении и при перезагрузке сервера. Не перезапускается, только если вы его остановили вручную командой docker stop.
Другие варианты: --restart always (перезапускать всегда), --restart on-failure (только при ошибке), --restart no (никогда).
Запускать каждый контейнер отдельной командой docker run с десятком параметров — неудобно. Docker Compose позволяет описать все контейнеры в одном YAML-файле и управлять ими одной командой.
Создайте директорию для проекта:
bashmkdir -p /opt/smarthome
cd /opt/smarthomeСоздайте файл docker-compose.yml:
bashnano docker-compose.ymlМинимальный пример — Mosquitto:
yamlservices:
mosquitto:
image: eclipse-mosquitto:2
container_name: mosquitto
restart: unless-stopped
ports:
- "1883:1883"
volumes:
- ./mosquitto/config:/mosquitto/config
- ./mosquitto/data:/mosquitto/data
- ./mosquitto/log:/mosquitto/logСохраните (Ctrl+O, Enter, Ctrl+X в nano).
bashdocker compose up -dDocker Compose скачает образ, создаст контейнер с указанными параметрами и запустит его. Флаг -d — в фоне.
Все команды выполняются из директории, где лежит docker-compose.yml.
bashdocker compose up -d # запустить все сервисы
docker compose down # остановить и удалить все контейнеры
docker compose stop # остановить (без удаления)
docker compose start # запустить остановленные
docker compose restart # перезапустить все
docker compose restart mosquitto # перезапустить один сервис
docker compose logs -f # логи всех сервисов
docker compose logs -f mosquitto # логи одного сервиса
docker compose ps # статус контейнеров
docker compose pull # скачать обновлённые образыbashdocker compose pull # скачать новые версии образов
docker compose up -d # пересоздать контейнеры из новых образовДанные в примонтированных директориях сохраняются. Обновляется только сам контейнер (код приложения, библиотеки). Конфигурация и данные — на месте.
Для отката на предыдущую версию — укажите конкретный тег в docker-compose.yml:
yamlimage: eclipse-mosquitto:2.0.18 # конкретная версия вместо "2" (последняя)И выполните docker compose up -d.
Теперь — реальный пример. Файл docker-compose.yml, который поднимает базовую инфраструктуру: Mosquitto, Zigbee2MQTT и Home Assistant.
bashmkdir -p /opt/smarthome
cd /opt/smarthome
mkdir -p mosquitto/config mosquitto/data mosquitto/log
mkdir -p zigbee2mqtt/data
mkdir -p homeassistant/configСоздайте файл конфигурации:
bashnano mosquitto/config/mosquitto.confСодержимое:
listener 1883
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
allow_anonymous false
password_file /mosquitto/config/passwdСохраните. Теперь создайте файл паролей (пока пустой — заполним после первого запуска).
yamlservices:
mosquitto:
image: eclipse-mosquitto:2
container_name: mosquitto
restart: unless-stopped
ports:
- "1883:1883"
volumes:
- ./mosquitto/config:/mosquitto/config
- ./mosquitto/data:/mosquitto/data
- ./mosquitto/log:/mosquitto/log
zigbee2mqtt:
image: koenkk/zigbee2mqtt
container_name: zigbee2mqtt
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./zigbee2mqtt/data:/app/data
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
depends_on:
- mosquitto
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: homeassistant
restart: unless-stopped
network_mode: host
volumes:
- ./homeassistant/config:/config
privileged: true
depends_on:
- mosquittomosquitto:
image: eclipse-mosquitto:2 — образ Mosquitto, последняя версия ветки 2.x.ports: "1883:1883" — MQTT-порт доступен из локальной сети.volumes — конфигурация, данные и логи хранятся на хосте.zigbee2mqtt:
image: koenkk/zigbee2mqtt — образ Zigbee2MQTT (latest).ports: "8080:8080" — веб-интерфейс Zigbee2MQTT.devices: /dev/ttyUSB0:/dev/ttyUSB0 — проброс USB-координатора (Sonoff ZBDongle, SMLIGHT и т.д.) внутрь контейнера. Путь может отличаться — проверьте командой ls /dev/ttyUSB* или ls /dev/ttyACM*.depends_on: mosquitto — Zigbee2MQTT стартует после Mosquitto.homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable — стабильная версия Home Assistant.network_mode: host — контейнер использует сеть хоста напрямую. Нужно для mDNS-обнаружения устройств. При host-режиме ports не указывают — все порты контейнера и так доступны на хосте. Home Assistant будет на порту 8123.privileged: true — расширенные права. Нужно для доступа к оборудованию (Bluetooth, USB). Для продвинутых пользователей — можно ограничить конкретными capabilities, но для начала privileged работает.depends_on: mosquitto — стартует после Mosquitto.bashdocker compose up -dПервый запуск — Docker скачает три образа (может занять несколько минут, зависит от скорости интернета). Затем создаст и запустит контейнеры.
После первого запуска Mosquitto создайте пользователя:
bashdocker exec -it mosquitto mosquitto_passwd -c /mosquitto/config/passwd homeassistantВведите пароль. Добавьте ещё пользователей (без флага -c, чтобы не перезаписать файл):
bashdocker exec -it mosquitto mosquitto_passwd /mosquitto/config/passwd zigbee2mqttПерезапустите Mosquitto:
bashdocker compose restart mosquittohttp://IP-сервера:8123http://IP-сервера:8080Если всё открывается — поздравляю, базовая инфраструктура работает.
Инфраструктура растёт — добавляем сервисы в тот же docker-compose.yml.
Добавьте в раздел services::
yaml influxdb:
image: influxdb:2
container_name: influxdb
restart: unless-stopped
ports:
- "8086:8086"
volumes:
- ./influxdb/data:/var/lib/influxdb2
- ./influxdb/config:/etc/influxdb2
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=admin
- DOCKER_INFLUXDB_INIT_PASSWORD=changeme123
- DOCKER_INFLUXDB_INIT_ORG=home
- DOCKER_INFLUXDB_INIT_BUCKET=homeassistant
grafana:
image: grafana/grafana
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- ./grafana/data:/var/lib/grafana
depends_on:
- influxdbСоздайте директории:
bashmkdir -p influxdb/data influxdb/config grafana/dataЗапустите:
bashdocker compose up -dDocker создаст только новые контейнеры — уже работающие не тронет.
http://IP-сервера:8086http://IP-сервера:3000 (логин: admin, пароль: admin — поменяйте при первом входе)yaml adguardhome:
image: adguard/adguardhome
container_name: adguardhome
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "3003:3000/tcp"
volumes:
- ./adguardhome/work:/opt/adguardhome/work
- ./adguardhome/conf:/opt/adguardhome/confПорт 3003 на хосте (потому что 3000 уже занят Grafana) → порт 3000 внутри контейнера (веб-интерфейс AdGuard Home).
yaml npm:
image: jc21/nginx-proxy-manager:latest
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "81:81"
volumes:
- ./npm/data:/data
- ./npm/letsencrypt:/etc/letsencryptВеб-интерфейс: http://IP-сервера:81 (логин: admin@example.com, пароль: changeme — поменяйте сразу).
yaml portainer:
image: portainer/portainer-ce
container_name: portainer
restart: unless-stopped
ports:
- "9000:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./portainer/data:/data/var/run/docker.sock — Docker-сокет, через который Portainer управляет контейнерами. Веб-интерфейс: http://IP-сервера:9000.
bashdocker compose psbashdocker statsРеалтайм-таблица с CPU, RAM, сетевым трафиком. Ctrl+C для выхода.
Иногда нужно выполнить команду внутри контейнера — проверить файлы, запустить утилиту:
bashdocker exec -it mosquitto shВы окажетесь внутри контейнера, в его файловой системе. exit — выход обратно на хост.
Для контейнеров на базе Debian/Ubuntu — вместо sh используйте bash.
Для Zigbee-координатора важно знать правильный путь:
bashls -la /dev/ttyUSB*
ls -la /dev/ttyACM*Если координатор — единственное USB-устройство, обычно это /dev/ttyUSB0 или /dev/ttyACM0.
Для стабильности рекомендуется использовать путь по ID:
bashls -la /dev/serial/by-id/Вывод будет вроде usb-Silicon_Labs_Sonoff_Zigbee_3.0_USB_Dongle_Plus_xxxx-if00-port0. Используйте этот путь в docker-compose.yml:
yamldevices:
- /dev/serial/by-id/usb-Silicon_Labs_Sonoff_Zigbee_3.0_USB_Dongle_Plus_xxxx-if00-port0:/dev/ttyACM0Так координатор будет найден даже если порядок USB-устройств изменится после перезагрузки.
Со временем на диске накапливаются старые версии образов:
bashdocker image prune -aУдалит все образы, которые не используются ни одним контейнером. Освобождает гигабайты.
bashdocker system prune -aБолее агрессивная очистка: неиспользуемые образы, остановленные контейнеры, неиспользуемые сети и кэш сборки.
С Docker резервное копирование — это два элемента.
docker-compose.yml — описание всей инфраструктуры.volumes.В нашем примере — это вся директория /opt/smarthome:
/opt/smarthome/
├── docker-compose.yml
├── mosquitto/
│ ├── config/
│ ├── data/
│ └── log/
├── zigbee2mqtt/
│ └── data/
├── homeassistant/
│ └── config/
├── influxdb/
│ ├── data/
│ └── config/
├── grafana/
│ └── data/
└── ...bash# Остановить контейнеры (для консистентности)
cd /opt/smarthome
docker compose stop
# Создать архив
tar czf /backup/smarthome-$(date +%Y%m%d).tar.gz /opt/smarthome/
# Запустить обратно
docker compose startДля InfluxDB и других баз данных остановка перед бэкапом — рекомендуется, чтобы не получить повреждённую копию. Для файлов конфигурации (Home Assistant, Zigbee2MQTT, Mosquitto) — можно копировать на ходу, но остановка надёжнее.
bashcrontab -eДобавьте строку:
0 3 * * * cd /opt/smarthome && docker compose stop && tar czf /backup/smarthome-$(date +\%Y\%m\%d).tar.gz /opt/smarthome/ && docker compose startКаждую ночь в 3:00 — остановка, бэкап, запуск. Контейнеры недоступны 1–5 минут.
tar xzf smarthome-20260305.tar.gz -C /cd /opt/smarthomedocker compose up -dВсё. Весь умный дом восстановлен на новом сервере.
Got permission denied while trying to connect to the Docker daemon socketВы не добавили пользователя в группу docker. Выполните sudo usermod -aG docker $USER и перелогиньтесь.
Смотрите логи:
bashdocker compose logs имя-сервисаЧастые причины: неверная конфигурация, отсутствующий файл, занятый порт.
Bind for 0.0.0.0:1883 failed: port is already allocatedПорт уже занят другим процессом или контейнером. Проверьте:
bashsudo lsof -i :1883Или смените порт хоста в docker-compose.yml: "1884:1883".
Координатор не найден по указанному пути. Проверьте ls /dev/serial/by-id/, убедитесь что устройство подключено, и обновите путь в docker-compose.yml.
Все контейнеры в одном docker-compose.yml автоматически в одной сети. Обращайтесь по имени сервиса (не container_name, а имени из YAML). Исключение: контейнер с network_mode: host (Home Assistant) — он в сети хоста и обращается к другим контейнерам через localhost:порт или IP-хоста:порт.
Вы не примонтировали директорию. Всё, что не в volumes, живёт только внутри контейнера и исчезает при его удалении. Добавьте volumes для всех данных, которые должны сохраняться.
Откатитесь на предыдущую версию. В docker-compose.yml укажите конкретный тег:
yamlimage: koenkk/zigbee2mqtt:1.40.0 # вместо latestИ выполните docker compose up -d.
yaml# Плохо — непредсказуемо
image: koenkk/zigbee2mqtt
# Хорошо — предсказуемо
image: koenkk/zigbee2mqtt:1.42.0Тег latest (используется по умолчанию, когда тег не указан) означает «последняя версия». Сегодня это 1.42.0, завтра — 1.43.0 с возможными несовместимостями. Для стабильности указывайте конкретную версию. Обновляйтесь осознанно, проверив changelog.
Исключение: Home Assistant (:stable) и Mosquitto (:2) — здесь мажорные версии стабильны, и тег ветки безопасен.
bashcd /opt/smarthome
git init
git add docker-compose.yml
git commit -m "Initial setup"Каждое изменение — коммит. История изменений, возможность отката, понимание, что и когда менялось. Не добавляйте в Git файлы с паролями и токенами — используйте .gitignore или переменные окружения через файл .env.
Создайте файл .env рядом с docker-compose.yml:
MQTT_PASSWORD=supersecretpassword
INFLUXDB_PASSWORD=anothersecretВ docker-compose.yml:
yamlenvironment:
- DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PASSWORD}Docker Compose автоматически подставит значения из .env. Добавьте .env в .gitignore, чтобы секреты не попали в Git.
Для домашнего сервера один файл — проще. Все сервисы в одной сети, одна команда для управления, один бэкап.
Если сервисов много (15+) и хочется группировать — можно разделить на несколько файлов в разных директориях. Но для начала — один файл на всё.
Docker установлен, базовая инфраструктура работает. Дальше — по потребностям:
docker-compose.yml с пробросом GPU/Coral.Каждый новый сервис — это ещё один блок в docker-compose.yml. Десять строк — и он работает. В этом сила Docker: вся инфраструктура умного дома описана в одном текстовом файле, который помещается на экран.
Статья подготовлена на основе официальной документации Docker и Docker Compose, а также практического опыта сообщества Home Assistant. Все команды проверены на Debian 12 и Ubuntu 24.04. Материал носит информационный характер и не является рекламой.