MAATRIX / Блог / ESPHome в Docker Compose: готовый файл

ESPHome в Docker Compose: готовый файл

MAATRIX

Если у вас дома или в мастерской набралось больше двух-трёх самодельных устройств на ESP8266/ESP32, ручная прошивка через Arduino IDE быстро превращается в рутину: копипаста кода, конфликты библиотек, забытые пины. ESPHome убирает весь этот код — вы описываете устройство в YAML, а компилятор сам собирает прошивку и заливает её по воздуху. Разберём, как поднять ESPHome в Docker Compose, чтобы не держать его вручную запущенным на ноутбуке, и на что обратить внимание, когда дашборд переезжает на отдельный сервер.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое ESPHome и когда его стоит выносить в Docker Compose

ESPHome — это фреймворк для прошивки микроконтроллеров ESP8266, ESP32 и их вариаций (C3, S2, S3) декларативным YAML-конфигом вместо C++. Вы описываете пины, датчики, реле, дисплеи — фреймворк сам генерирует и компилирует прошивку через PlatformIO. Готовое устройство публикует состояние по MQTT или напрямую по нативному API, которое понимает Home Assistant.

Штатно ESPHome ставится как аддон Home Assistant OS или запускается локально через pip. Но если у вас уже есть VPS под другие сервисы — панель мониторинга, Node-RED, обратный прокси — логично держать и дашборд ESPHome там же в контейнере: единая точка управления конфигами всех устройств, версионирование через git, не нужно держать компьютер включённым ради редких перепрошивок.

Важная оговорка сразу: первую прошивку устройства почти всегда проще сделать локально, с USB-кабелем воткнутым в тот компьютер, где физически лежит ESP32. После первой заливки все последующие обновления идут по Wi-Fi (OTA), и вот тут уже без разницы, где крутится дашборд — хоть на VPS в другой стране, если у сервера есть сетевой путь к устройствам. Как организовать этот путь — отдельный разговор, разберём его в разделе про сеть.

Готовый docker-compose.yml для ESPHome

Официальный образ esphome/esphome включает и сам компилятор, и веб-дашборд. Вот рабочий файл:

services:
  esphome:
    image: esphome/esphome:2025.8.0
    container_name: esphome
    restart: unless-stopped
    privileged: true
    network_mode: host
    environment:
      - USERNAME=admin
      - PASSWORD=${ESPHOME_PASSWORD}
      - ESPHOME_DASHBOARD_USE_PING=true
    volumes:
      - ./config:/config
      - /etc/localtime:/etc/localtime:ro

Пара моментов, которые часто упускают:

  • network_mode: host обязателен, если хотите, чтобы дашборд видел устройства через mDNS (Bonjour/Avahi) в локальной сети. На VPS с отдельным сетевым сегментом mDNS всё равно не долетит до домашней сети напрямую — об этом ниже.
  • privileged: true нужен, только если вы планируете прошивать устройства через USB, воткнутый прямо в сервер (то есть сервер физически стоит дома рядом с роутером). Для чисто облачного VPS, где USB-прошивки не будет, этот флаг можно убрать и вместо него смонтировать конкретное устройство через devices:.
  • Пароль дашборда берите из .env, не хардкодьте в файле.

Файл .env рядом:

ESPHOME_PASSWORD=сложный_пароль_сюда

Поднимаем:

docker compose up -d
docker compose logs -f esphome

Дашборд открывается на порту 6052: http://IP-сервера:6052.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Структура проекта и secrets.yaml

ESPHome хранит все конфиги устройств прямо в папке config/, которую вы примонтировали как volume. Структура получается такая:

config/
├── secrets.yaml
├── kuhnya-datchik.yaml
├── balkon-rele.yaml
└── .esphome/
    ├── build/
    └── storage.json

secrets.yaml — общий файл с чувствительными данными, который не должен светиться в конфигах устройств и, соответственно, не должен попадать в публичный git-репозиторий:

wifi_ssid: "MyHomeWiFi"
wifi_password: "пароль_от_wifi"
api_encryption_key: "base64-ключ-32-байта"
ota_password: "отдельный_пароль_для_ota"
fallback_password: "пароль_для_captive_portal"

Ключ шифрования API генерируется командой:

openssl rand -base64 32

Если вы храните конфиги в git (что стоит делать — конфиги ESP-устройств текстовые и отлично версионируются), добавьте secrets.yaml в .gitignore и держите его копию отдельно, например зашифрованной через git-crypt или просто вне репозитория.

Первая прошивка: локально, потом OTA через сервер

Реалистичный рабочий процесс выглядит так:

  1. Дома, с ноутбука или Raspberry Pi, к которому физически подключён ESP32 по USB, ставите ESPHome локально (pip install esphome) или используете веб-инсталлятор прямо из Chrome — он прошивает через WebSerial без установки чего-либо.
  2. Пишете первичный YAML-конфиг устройства (см. пример ниже) и заливаете его командой esphome run kuhnya-datchik.yaml — на этом шаге устройство получает Wi-Fi-данные и API-ключ.
  3. Копируете этот же YAML-файл в папку config/ на сервере — например, через git push в репозиторий, который сервер потом pull-ит, или просто scp.
  4. С этого момента сервер видит устройство как уже подключённое к Wi-Fi, и все последующие изменения конфига заливаются кнопкой "Install → Wireless" прямо из веб-дашборда — без USB, по сети.

Если устройств много и вы прошиваете их пачками, USB-этап можно ускорить массовым скриптом на первичную заливку, но сам факт первого физического подключения обойти нельзя — это ограничение протокола ESP-Now/Wi-Fi, а не ESPHome.

Пример YAML-конфига устройства

Типовой конфиг для ESP32 с датчиком температуры/влажности DHT22 и одним реле:

esphome:
  name: kuhnya-datchik
  friendly_name: "Кухня — датчик и реле"

esp32:
  board: esp32dev
  framework:
    type: arduino

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "Kuhnya-Fallback"
    password: !secret fallback_password

captive_portal:

api:
  encryption:
    key: !secret api_encryption_key

ota:
  platform: esphome
  password: !secret ota_password

logger:
  level: INFO

sensor:
  - platform: dht
    pin: GPIO4
    model: DHT22
    temperature:
      name: "Кухня Температура"
    humidity:
      name: "Кухня Влажность"
    update_interval: 60s

switch:
  - platform: gpio
    pin: GPIO5
    name: "Кухня Реле вытяжки"
    id: relay_1

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO0
      mode: INPUT_PULLUP
      inverted: true
    name: "Кухня Кнопка"
    on_press:
      then:
        - switch.toggle: relay_1

Секция ap: — важная страховка: если устройство не может подключиться к домашнему Wi-Fi (роутер перезагрузился, пароль сменили), оно поднимает собственную точку доступа с captive-порталом, через которую можно зайти и перенастроить Wi-Fi без переподключения по USB. Не убирайте её, даже если кажется лишней строкой.

Доступ к устройствам с сервера: сеть, mDNS и WireGuard

Вот та часть, где облачный VPS отличается от Raspberry Pi дома, и где стоит быть честным о нюансах. ESPHome-дашборд обнаруживает устройства двумя способами: через mDNS-broadcast в локальной сети и через прямое обращение по IP/hostname, прописанному в конфиге.

Если сервер стоит физически в той же сети, что и устройства (например, вы арендовали мини-сервер и подключили его к домашнему роутеру), mDNS работает как обычно, network_mode: host в docker-compose видит broadcast-пакеты — и всё "просто работает".

Если же дашборд крутится на удалённом VPS (что чаще всего и есть смысл делать — не держать же полноценный сервер дома ради ESPHome), multicast-трафик mDNS через интернет не пройдёт — это его фундаментальное ограничение, не баг конфигурации. Рабочий обходной путь:

  1. Поднимаете WireGuard-тоннель между домашним роутером/мини-компьютером и VPS, чтобы устройства и сервер оказались в одной приватной подсети (например, 10.10.0.0/24).
  2. В конфиге каждого устройства в ESPHome прописываете manual_ip: с фиксированным адресом или используете DHCP-резервацию на роутере, чтобы адрес не менялся.
  3. В дашборде на сервере используете кнопку "Install → Manually" с явным IP устройства вместо автообнаружения по mDNS — ESPHome прекрасно умеет заливать прошивку напрямую по адресу, обнаружение нужно только для удобства.

Это добавляет шаг настройки, зато даёт стабильный результат: дашборд на сервере, устройства дома, обновления заливаются по защищённому тоннелю, а не через что попало в открытом интернете.

Безопасность и автообновление

ESPHome-дашборд по умолчанию слушает на 6052 без TLS. Выставлять его напрямую в интернет — плохая идея: там лежат ключи API ваших устройств. Правильная схема — держать порт закрытым файрволом и заходить либо через WireGuard, либо через обратный прокси с базовой аутентификацией. Если у вас уже настроен Traefik как reverse proxy для Docker, добавить ESPHome под HTTPS с Basic Auth — вопрос десятка строк лейблов в compose-файле.

Что касается обновлений самого образа ESPHome — фреймворк развивается быстро, новые платы и компоненты добавляются каждый релиз. Пин конкретной версии в compose-файле (как в примере выше — 2025.8.0) убережёт от неожиданных breaking changes при пересборке прошивок, но версию всё равно стоит поднимать вручную и осознанно, читая changelog, а не через слепой auto-pull. Если вы предпочитаете автоматизировать это для менее критичных сервисов, у нас есть отдельный разбор автообновления контейнеров через Watchtower — для ESPHome я бы всё же рекомендовал исключить его из автопилота через label com.centurylinklabs.watchtower.enable=false, потому что обновление компилятора может потребовать правки уже существующих YAML-конфигов.

Отдельно бэкапьте config/.esphome/storage.json и саму папку config/ целиком — это не только YAML, но и скомпилированные прошивки, которые ускоряют повторную сборку. Если весь стек умного дома у вас уже строится вокруг Home Assistant, у нас есть готовый docker-compose для Home Assistant — ESPHome отлично встраивается туда же как соседний сервис в том же compose-файле, а устройства подключаются к Home Assistant автоматически через интеграцию ESPHome по нативному API.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли прошить ESP32 в первый раз без USB-кабеля, сразу через сервер?

Технически да, через веб-инсталлятор ESPHome с телефона или ноутбука рядом с устройством — но физическая близость к устройству и передача Wi-Fi-данных всё равно нужны на первом шаге. Полностью удалённо прошить "с нуля" устройство, до которого вы никогда не дотрагивались, нельзя.

ESPHome обязательно работать вместе с Home Assistant?

Нет, дашборд ESPHome самодостаточен — можно собирать и заливать прошивки, вообще не имея Home Assistant. Но без него вы теряете автоматизации, историю показаний и единый интерфейс — интеграция с HA практически бесплатна (пара кликов) и того стоит.

Что делать, если устройство перестало откликаться после OTA-обновления?

Обычно помогает fallback точка доступа, описанная в секции ap: конфига — подключитесь к ней с телефона и перезайдите на веб-интерфейс устройства по адресу 192.168.4.1. Если и это не помогает — потребуется повторная прошивка по USB.

Нужен ли мощный сервер под ESPHome?

Нет, компиляция прошивки для одного устройства занимает секунды-десятки секунд и почти не грузит CPU. Минимальный VPS с 1 vCPU и 1-2 ГБ RAM спокойно тянет дашборд на десятки устройств вместе с другими лёгкими сервисами.

Как перенести уже настроенные устройства с локального ESPHome на сервер?

Просто скопируйте всю папку config/ на новый хост и запустите тот же compose-файл — дашборд подхватит существующие конфиги и историю сборок, повторная прошивка не требуется, пока IP и API-ключи устройств не менялись.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →