Skip to content

ESPHome docker container that supports non-root operation

License

Notifications You must be signed in to change notification settings

ptr727/ESPHome-NonRoot

Repository files navigation

ESPHome-NonRoot

ESPHome docker container that supports non-root operation.

License

Licensed under the MIT License
GitHub License

Build

Code and Pipeline is on GitHub.
Docker image is published on Docker Hub.
Image is rebuilt weekly, or when a new ESPHome version is released, picking up the latest ESPHome release and upstream container updates.

Status

Last Commit
Workflow Status
Last Build
Docker Latest

Release Notes

  • Version 1.2:
  • Version 1.1:
    • Added daily actions job to trigger a build if the ESPHome version changed.
  • Version 1.0:
    • Initial public release.

Usage

Configuration

  • volumes :
    • /config : Volume mapping to project files, e.g. /data/esphome/config:/config.
    • /cache : Volume mapping to runtime generated content, e.g. /data/esphome/cache:/cache.
  • user (Optional) : Run the container under the specified user account.
    • Use the uid:gid notation, e.g. user: 1001:100.
      • Get the uid : sudo id -u nonroot.
      • Get the gid : sudo id -g nonroot.
    • Use an existing user or create a system account on the host.
      • adduser --no-create-home --shell /bin/false --disabled-password --system --group users nonroot.
    • Omitting the user option will run under default root account.
    • Make sure the container user has permissions to the mapped /config and /cache volumes.
      • sudo chown -R nonroot:users /data/esphome
      • sudo chmod -R ugo=rwx /data/esphome
  • environment :
    • ESPHOME_VERBOSE (Optional) : Add the --verbose option when running the dashboard, e.g. ESPHOME_VERBOSE=true.
    • ESPHOME_DASHBOARD_USE_PING (Optional) : Use ping instead of mDNS to test if nodes are up, e.g. ESPHOME_DASHBOARD_USE_PING=true.
    • TZ (Optional) : Sets the timezone, e.g. TZ=America/Los_Angeles, default is Etc/UTC.

Examples

Docker Compose Dashboard

services:
  esphome:
    image: docker.io/ptr727/esphome-nonroot:latest
    container_name: esphome-test
    restart: unless-stopped
    user: 1001:100
    environment:
      - TZ=America/Los_Angeles
      - ESPHOME_VERBOSE=true
      - ESPHOME_DASHBOARD_USE_PING=true
    network_mode: bridge
    ports:
      - 6052:6052
    volumes:
      - /data/esphome/config:/config
      - /data/esphome/cache:/cache
# Create nonroot user
adduser --no-create-home --shell /bin/false --disabled-password --system --group users nonroot
id nonroot
# uid=1001(nonroot) gid=100(users) groups=100(users)

# Prepare directories for use by nonroot:users
mkdir -p /data/esphome/config /data/esphome/cache
sudo chown -R nonroot:users /data/esphome
sudo chmod -R ugo=rwx /data/esphome

# Launch stack
docker compose --file ./Docker/Compose.yml up --detach

# Open browser: http://localhost:6052
# Attach shell: docker exec -it --user 1001:100 esphome-test /bin/bash

# Destroy stack
docker compose --file ./Docker/Compose.yml down --volumes

Docker Run Command

# esphome version
docker run --rm --pull always --name esphome-test -v /data/esphome/config:/config -v /data/esphome/cache:/cache ptr727/esphome-nonroot:latest esphome version
latest: Pulling from ptr727/esphome-nonroot
Digest: sha256:8f32848551446d0420390477fccb8c833d879b640b95533f443cb623882e9688
Status: Image is up to date for ptr727/esphome-nonroot:latest
Version: 2024.5.5

Docker Run Interactive Shell

# /bin/bash
docker run --rm --user 1001:100 -it --pull always --name esphome-test -v /data/esphome/config:/config -v /data/esphome/cache:/cache ptr727/esphome-nonroot:latest /bin/bash
latest: Pulling from ptr727/esphome-nonroot
Digest: sha256:8f32848551446d0420390477fccb8c833d879b640b95533f443cb623882e9688
Status: Image is up to date for ptr727/esphome-nonroot:latest
I have no name!@012d4b62d376:/config$ id
uid=1001 gid=100(users) groups=100(users)
I have no name!@012d4b62d376:/config$

Use Case

  • Running containers as non-privileged and as non-root is a docker best practice.
  • The official ESPHome docker container does not support running as a non-root user.
  • Issue analysis based on ESPHome 2024.5.5 (current version as of writing) Dockerfile:
    • PLATFORMIO_GLOBALLIB_DIR=/piolibs sets the PlatformIO globallib_dir option to /piolibs.
      • /piolibs is not mapped to an external volume.
      • /piolibs has default permissions and requires root write permissions at runtime.
      • The globallib_dir option has been deprecated.
        • This option is DEPRECATED. We do not recommend using global libraries for new projects. Please use a declarative approach for the safety-critical embedded development and declare project dependencies using the lib_deps option.
    • platformio_install_deps.py installs global libraries using pio pkg install -g, the -g option has been deprecated.
      • We DO NOT recommend installing libraries in the global storage. Please use the lib_deps option and declare library dependencies per project.
    • The presence of a /cache directory changes pio_cache_base to /cache/platformio, the default is /config/.esphome/platformio
      • PLATFORMIO_PLATFORMS_DIR="${pio_cache_base}/platforms", PLATFORMIO_PACKAGES_DIR="${pio_cache_base}/packages", and PLATFORMIO_CACHE_DIR="${pio_cache_base}/cache" is explicitly set as child directories of pio_cache_base.
      • It is simpler to set PLATFORMIO_CORE_DIR PlatformIO core_dir option, and not setting PLATFORMIO_PLATFORMS_DIR platforms_dir, PLATFORMIO_PACKAGES_DIR packages_dir, and PLATFORMIO_CACHE_DIR cache_dir options, that are by default child directories of core_dir.
    • The presence of a /build directory sets the ESPHOME_BUILD_PATH environment variable, that sets the CONF_BUILD_PATH ESPHome build_path option, the default is /config/.esphome/build.
      • The directory presence detection could override an explicitly set ESPHOME_BUILD_PATH option.
    • ESPHOME_DATA_DIR can be used to set the ESPHome data_dir intermediate build output directory, the default is /config/.esphome, or hardcoded to /data for the HA addon image.
    • PLATFORMIO_CORE_DIR PlatformIO core_dir option is not set and defaults to ~/.platformio.
    • PIP_CACHE_DIR is not set and defaults to ~/.cache/pip.
    • HOME (~) is not set and defaults to e.g. /home/[username] or / or /nonexistent that either does not exists or the executing user does not have write permissions.

Project Design

  • Use the python:slim Debian based Python docker image as a base image simplifying use for Python in a container environment.
  • Use a multi-stage build minimizing size and layer complexity of the final stage.
  • Build wheel archives for the platform in the builder stage, and install from the generated wheel packages in the final stage.
  • Set appropriate PlatformIO and ESPHome environment variables to store projects in /config and dynamic and temporary content in /cache volumes.
  • Refer to Dockerfile for container details.
  • Refer to BuildDockerPush.yml and for pipeline details.

Debugging

The included Dev Container can be used for ESPHome Python or PlatformIO C++ debugging in VSCode.

TODO:
Detailed debug setup details are beyond the scope of this document, refer to my ESPHome-Config project for slightly more complete debugging setup instructions.

About

ESPHome docker container that supports non-root operation

Topics

Resources

License

Stars

Watchers

Forks