Setting up HomeAssistant + ESPHome under docker?

Hi,

I’m trying to setup some Bluetooth proxies (GL.iNet GL-S10) in HomeAssistant. I did have the ESPHome integration added previously to my HomeAssistant install, and so it was able to pickup the new GL-S10 device, and add it to the HomeAssistant dashboard:

However, I got a notification saying the firmware was out of date - so I thought I’d try and update the firmware on the device.

The ESPHome Getting Started documentation mentions that you want to install a “ESPHome Device Builder”, which is available as a HomeAssistant Add-on.

However, I’m running HomeAssistant in Docker, which means I can’t run HomeAssistant add-ons.

Anyway, I then modified my docker compose file, to add a section for esphome - my new compose.yml file is below:

services:
  homeassistant:
    labels:
      - traefik.enable=true
      - traefik.http.services.ha.loadbalancer.server.port=8123
      - traefik.http.routers.ha.rule=Host(`homeassistant.victorhooi.com`)
      - traefik.http.routers.ha.entrypoints=web
    container_name: homeassistant
    image: "ghcr.io/home-assistant/home-assistant:dev"
    volumes:
      - /home/victorhooi/homeassistant-docker/config:/config
      - /etc/localtime:/etc/localtime:ro
      - /run/dbus:/run/dbus:ro
    restart: unless-stopped
    privileged: true
    network_mode: host
  mosquitto:
    container_name: mosquitto
    image: eclipse-mosquitto
    restart: unless-stopped
  #  friendly_name: '0x84b4dbfffe96fea8'
    volumes:
      - ./mosquitto/config:/mosquitto/config
      - ./mosquitto/data:/mosquitto/data
      - ./mosquitto/log:/mosquitto/log
    ports:
      - 1883:1883
      - 9001:9001
    environment:
      TZ: "Australia/Sydney"
  zigbee2mqtt:
    container_name: zigbee2mqtt
    image: koenkk/zigbee2mqtt:latest-dev
    restart: unless-stopped
    volumes:
      - ./zigbee2mqtt/data:/app/data
      - /run/udev:/run/udev:ro
    ports:
    # Frontend port
      - 8080:8080
    environment:
      - TZ=Australia/Sydney
  esphome:
    container_name: esphome
    image: ghcr.io/esphome/esphome
    volumes:
      - ./esphome/config:/config
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped
    privileged: true
    network_mode: host
    environment:
      - USERNAME=victorhooi
      - PASSWORD=loremipsum

I’ve spun up the containers - I can access the ESPHome web UI at port 6052. However, it doesn’t list any devices here.

Just to confirm - the ESPHome devices I add in HomeAssistant - is that completely separate to the devices that are listed on this ESPHome dashboard, at port 6052?

Also, I’m getting an error message that I need to access this over HTTPS, in order to modify devices?

Is the assumption that you setup something like Nginx or Caddy as well, in order to front the ESPHome docker image as well?

It all seems a bit complicated - so I’m thinking possibly I’m missing something obvious here - surely heaps of other people are running HA + ESPHome under docker?

Has anybody posted a configuration, or guide, to setting up HomeAssistant + ESPHome in docker, where everything works as it should?

Yes. This is where the yaml for devices you configured yourself are kept. If you have a Bluetooth proxy or voice assistant you configured using the website, they won’t be there.

If you want to be using the upgrade button in HA - I think there is some extra config you need. About halfway down in the first post of this thread is some config for pointing HA to your ESPHome docker container. I’ve never tried it so don’t know if it works.

Not exactly. But there are a number of combinations they’re trying to cover. When you go to install (flash) the device, you have four choices, shown below.

The first only works if the device has already been flashed with esphome. The second, where “this computer” refers to the one running the browser, only works if that browser is chromium-based and using a https connection. The third requires you to get up and plug the device into the esphome builder (docker) machine, which might be located remotely from where you’re browsing. The last works in all scenarios but requires a third-party flashing tool like esptool.py (I use this on my Mac for initial flashing, and do not use https).

Your docker config looks good to me. If it has direct (i.e. non-routed) access to the esphome device, it should be auto-detected and ask you to “adopt” it. If the manufacturer put the dashboard_import info into the config, which it appears to, it will pull the config from GitHub so you can compile it and install the latest version. If you’re using routed vlans then auto discovery will run into problems.

Thanks for the pointer to that thread - I did do a quick skim, I couldn’t seem to find the part you referred to, but I might try reading it again in the morning, when I’m not so tired, haha.

Oh - that would be really great if it could work like that!

Yes, the ESPHome device (GL-S10) and the server (running HomeAssistant, and also the ESPHome docker container) are both on the same Layer 2 network.

I can ping it, it’s online, it’s only 1 hope away…(sorry…dad joke):

victorhooi@ampere-01 ~/homeassistant-docker> traceroute 10.5.1.46
traceroute to 10.5.1.46 (10.5.1.46), 30 hops max, 60 byte packets
 1  10.5.1.46 (10.5.1.46)  0.918 ms  1.178 ms  1.375 ms

However, the dashboard doesn’t seem to show any discovered devices that I can “adopt”:

In the top right, if I click the three dots, I’ve also selected “Show discovered devices” - however, it still doesn’t show anything:

If I know the IP address of the ESPHome device, is there some way to manually add it to the ESPHome Device Builder, and adopt it that way?

The fact that the ESPHome Integration in HomeAssistant has already discovered the device and added it - that shouldn’t have any bearing on ESPHome Device Builder discovering it, right?

Thanks to your mention of “adopt” as the keyboard, I tried to do a search - found these other threads:

I’ve tried re-creating the Docker container, and adding the environment variable:

      - ESPHOME_DASHBOARD_USE_PING=true

However, it still doesn’t seem to show up for adoption then either :confused:.

Copy your yaml-Files for the Esphome-Devices into the Esphome-“Config”-Folder, unlike Home Assistant the Esphome Dashboard does not detect the devices on the network, it reads the yaml and detects the devices by their name or IP.

You’ll likely need to add MDNS ports and protocols to you docker config. UDP 5353.

AFAIK, ESPHOME_DASHBOARD_USE_PING is only used for online/offline status, there isn’t an easy way for it to use ping for discovery. At least I don’t understand how that would work :slight_smile:

Looks like your network_mode: host should have worked for MDNS. You’ll likely need to do some troubleshooting in the docker container to see if MDNS is truly working.

Maybe avahi daemon isn’t running?

Just a quick update - I was able to update the GL-S10 via OTA. My notes are below for posterity, or in case anybody else (or future me) stumbles across this.

Initially, I thought I’d try installing esphome locally on my Macbook (via nix). I used the stock YAML file from the ESPHome devices page for the GL-S10, and ran:

esphome run s10.yaml  --device 10.5.1.46

However, I ended up with a bunch of compile errors:

HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-espidf @ 3.50402.0 (5.4.2)
 - tool-cmake @ 3.30.2
 - tool-esp-rom-elfs @ 2024.10.11
 - tool-esptoolpy @ 5.0.2
 - tool-mklittlefs @ 3.2.0
 - tool-ninja @ 1.13.1
 - tool-scons @ 4.40801.0 (4.8.1)
 - toolchain-esp32ulp @ 2.35.0-20220830
 - toolchain-xtensa-esp-elf @ 14.2.0+20241119
Creating a new virtual environment for IDF Python dependencies
Installing ESP-IDF's Python dependencies
Reading CMake configuration...
-- Found Git: /nix/store/4q2dd3sf6xq9bky0aq2wyp2pf958j0rz-git-2.51.0/bin/git (found version "2.51.0")
-- git rev-parse returned 'fatal: not a git repository (or any of the parent directories): .git'
-- The C compiler identification is GNU 14.2.0
-- The CXX compiler identification is GNU 14.2.0
-- The ASM compiler identification is GNU
-- Found assembler: /Users/victorhooi/.platformio/packages/toolchain-xtensa-esp-elf/bin/xtensa-esp32-elf-gcc
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Users/victorhooi/.platformio/packages/toolchain-xtensa-esp-elf/bin/xtensa-esp32-elf-gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Users/victorhooi/.platformio/packages/toolchain-xtensa-esp-elf/bin/xtensa-esp32-elf-g++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Building ESP-IDF components for target esp32
Dependencies lock doesn't exist, solving dependencies.
..NOTICE: Updating lock file at /Users/victorhooi/Downloads/.esphome/build/gl-s10-bt-proxy/dependencies.lock
Processing 2 dependencies:
[1/2] espressif/mdns (1.8.2)
[2/2] idf (5.4.2)
-- Project sdkconfig file /Users/victorhooi/Downloads/.esphome/build/gl-s10-bt-proxy/sdkconfig.gl-s10-bt-proxy
-- Configuring incomplete, errors occurred!

fatal: not a git repository (or any of the parent directories): .git
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/Users/victorhooi/.platformio/penv/.espidf-5.4.2/lib/python3.13/site-packages/kconfgen/__main__.py", line 5, in <module>
    from .core import main
  File "/Users/victorhooi/.platformio/penv/.espidf-5.4.2/lib/python3.13/site-packages/kconfgen/core.py", line 29, in <module>
    import esp_idf_kconfig.gen_kconfig_doc as gen_kconfig_doc
  File "/Users/victorhooi/.platformio/penv/.espidf-5.4.2/lib/python3.13/site-packages/esp_idf_kconfig/gen_kconfig_doc.py", line 14, in <module>
    import kconfiglib.core as kconfiglib
ModuleNotFoundError: No module named 'kconfiglib.core'; 'kconfiglib' is not a package
CMake Error at /Users/victorhooi/.platformio/packages/framework-espidf/tools/cmake/kconfig.cmake:209 (message):
  Failed to run kconfgen
  (/Users/victorhooi/.platformio/penv/.espidf-5.4.2/bin/python;-m;kconfgen;--list-separator=semicolon;--kconfig;/Users/victorhooi/.platformio/packages/framework-espidf/Kconfig;--sdkconfig-rename;/Users/victorhooi/.platformio/packages/framework-espidf/sdkconfig.rename;--config;/Users/victorhooi/Downloads/.esphome/build/gl-s10-bt-proxy/sdkconfig.gl-s10-bt-proxy;--env-file;/Users/victorhooi/Downloads/.esphome/build/gl-s10-bt-proxy/.pioenvs/gl-s10-bt-proxy/config.env).
  Error 1
Call Stack (most recent call first):
  /Users/victorhooi/.platformio/packages/framework-espidf/tools/cmake/build.cmake:691 (__kconfig_generate_config)
  /Users/victorhooi/.platformio/packages/framework-espidf/tools/cmake/project.cmake:718 (idf_build_process)
  CMakeLists.txt:3 (project)



============================================================================================= [FAILED] Took 28.53 seconds =============================================================================================
victorhooi@mbp16-personal ~/Downloads [1]> ping 10.5.1.45

I guess that’s one of the advantages of containerise systems, Docker etc…:joy:. I could have setup Docker on my Mac, but I ended up just switching back to the server.

In this case, I used the ESPHome Device Builder (port 6052) (I think in theory you can use docker run to execute CLI against the container - but I didn’t want to risk breaking anything there). From the web UI clicked on “New Device”, then Continue, then “Import from File”, then selected the YAML file I had from above.

At first, I think it tried to find the device via a local DNS alias - either way, I had to specify the IP address. There were a bunch of posts online that mentioned using manual_ip - for Ethernet this would be:

ethernet:
  manual_ip:
    static_ip: <IP address>

However, this is not what I want, since then the device would actually be configured with a static IP address, not DHCP. It’s the use_address setting you want (discussion):

ethernet:
  use_address: <IP address>

The end result should be it successfully building, and pushing the firmware to the device, then rebooting:

Using FLASH_EXTRA_IMAGES from PlatformIO environment
Merging binaries into /config/.esphome/build/gl-s10-bt-proxy/.pioenvs/gl-s10-bt-proxy/firmware.factory.bin
Merging binaries with esptool
SHA digest in image updated.
Wrote 0xed410 bytes to file '/config/.esphome/build/gl-s10-bt-proxy/.pioenvs/gl-s10-bt-proxy/firmware.factory.bin', ready to flash to offset 0x0.
Successfully created /config/.esphome/build/gl-s10-bt-proxy/.pioenvs/gl-s10-bt-proxy/firmware.factory.bin
esp32_copy_ota_bin([".pioenvs/gl-s10-bt-proxy/firmware.bin"], [".pioenvs/gl-s10-bt-proxy/firmware.elf"])
Copied firmware to /config/.esphome/build/gl-s10-bt-proxy/.pioenvs/gl-s10-bt-proxy/firmware.ota.bin
========================= [SUCCESS] Took 13.03 seconds =========================
INFO Successfully compiled program.
INFO Connecting to 10.5.1.46 port 3232...
INFO Connected to 10.5.1.46
INFO Uploading /config/.esphome/build/gl-s10-bt-proxy/.pioenvs/gl-s10-bt-proxy/firmware.bin (906256 bytes)
Uploading: [============================================================] 100% Done...

INFO Upload took 3.17 seconds, waiting for result...
INFO OTA successful
INFO Successfully uploaded program.
INFO Starting log output from 10.5.1.46 using esphome API
INFO Successfully resolved gl-s10-bt-proxy @ 10.5.1.46 in 0.001s
WARNING Can't connect to ESPHome API for gl-s10-bt-proxy @ 10.5.1.46: Error connecting to [AddrInfo(family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, proto=6, sockaddr=IPv4Sockaddr(address='10.5.1.46', port=6053))]: [Errno 111] Connect call failed ('10.5.1.46', 6053) (SocketAPIError)
INFO Trying to connect to gl-s10-bt-proxy @ 10.5.1.46 in the background
INFO Successfully resolved gl-s10-bt-proxy @ 10.5.1.46 in 0.000s
INFO Successfully connected to gl-s10-bt-proxy @ 10.5.1.46 in 0.003s
INFO Successful handshake with gl-s10-bt-proxy-406228 @ 10.5.1.46 in 0.031s
[08:31:41.952][I][app:185]: ESPHome version 2025.9.2 compiled on Oct  2 2025, 08:31:10
[08:31:41.954][I][app:187]: Project gl-s10.bluetooth-proxy version 2.1
[08:31:41.955][C][status_led:018]: Status LED:
[08:31:41.957][C][status_led:019]:   Pin: GPIO32
[08:31:41.959][C][logger:273]: Logger:
[08:31:41.959][C][logger:273]:   Max Level: DEBUG
[08:31:41.959][C][logger:273]:   Initial Level: DEBUG

I assume if I’m flashing a new device (i.e. doesn’t have ESPHome), then I will need to get ESPHome (e.g. via Docker) working locally on my Macbook, so that I can push directly via the debug pins, right?

And it seems like the ESPHome Device Builder not picking up the devices - is that working as intended, or not? Or should it be using mDNS and picking those up somehow?

I didn’t see the mdns component listed on the stock GL-S10 configuration, but is it meant to be in there automatically, or should it work out of the box?