ESPHome docker container that supports non-root operation.
Licensed under the MIT License
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.
- Version 1.5:
- Using Python 3.13 base image.
- Version 1.4:
- Removed custom handling for
ESPHOME_VERBOSEenabling--verbose, PR merged.
- Removed custom handling for
- Version 1.3:
- Version 1.2:
- Delete temp directory contents and prune PIO cached content on startup.
- Added Dev Container that can be used for ESPHome or PlatformIO debugging.
- Version 1.1:
- Added daily actions job to trigger a build if the ESPHome version changed.
- Version 1.0:
- Initial public release.
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:gidnotation, e.g.user: 1001:100.- Get the
uid:sudo id -u nonroot. - Get the
gid:sudo id -g nonroot.
- Get the
- Use an existing user or create a system account on the host.
adduser --no-create-home --disabled-password --system --group users nonroot.
- Omitting the
useroption will run under defaultrootaccount. - Make sure the container user has permissions to the mapped
/configand/cachevolumes.sudo chown -R nonroot:users /data/esphomesudo chmod -R ug=rwx,o=rx /data/esphome
- Use the
environment:ESPHOME_VERBOSE(Optional) : Enables verbose log output, e.g.ESPHOME_VERBOSE=true.ESPHOME_DASHBOARD_USE_PING(Optional) : Usepinginstead ofmDNSto test if nodes are up, e.g.ESPHOME_DASHBOARD_USE_PING=true.TZ(Optional) : Sets the timezone, e.g.TZ=America/Los_Angeles, default isEtc/UTC.
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 --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 ug=rwx,o=rx /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# 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 versionlatest: Pulling from ptr727/esphome-nonroot
Digest: sha256:8f32848551446d0420390477fccb8c833d879b640b95533f443cb623882e9688
Status: Image is up to date for ptr727/esphome-nonroot:latest
Version: 2024.5.5# /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/bashlatest: 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$- 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=/piolibssets the PlatformIOgloballib_diroption to/piolibs./piolibsis not mapped to an external volume./piolibshas default permissions and requiresrootwrite permissions at runtime.- The
globallib_diroption 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.pyinstalls global libraries usingpio pkg install -g, the-goption 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
/cachedirectory changespio_cache_baseto/cache/platformio, the default is/config/.esphome/platformioPLATFORMIO_PLATFORMS_DIR="${pio_cache_base}/platforms",PLATFORMIO_PACKAGES_DIR="${pio_cache_base}/packages", andPLATFORMIO_CACHE_DIR="${pio_cache_base}/cache"is explicitly set as child directories ofpio_cache_base.- It is simpler to set
PLATFORMIO_CORE_DIRPlatformIOcore_diroption, and not settingPLATFORMIO_PLATFORMS_DIRplatforms_dir,PLATFORMIO_PACKAGES_DIRpackages_dir, andPLATFORMIO_CACHE_DIRcache_diroptions, that are by default child directories ofcore_dir.
- The presence of a
/builddirectory sets theESPHOME_BUILD_PATHenvironment variable, that sets theCONF_BUILD_PATHESPHomebuild_pathoption, the default is/config/.esphome/build.- The directory presence detection could override an explicitly set
ESPHOME_BUILD_PATHoption.
- The directory presence detection could override an explicitly set
ESPHOME_DATA_DIRcan be used to set the ESPHomedata_dirintermediate build output directory, the default is/config/.esphome, or hardcoded to/datafor the HA addon image.PLATFORMIO_CORE_DIRPlatformIOcore_diroption is not set and defaults to~/.platformio.PIP_CACHE_DIRis not set and defaults to~/.cache/pip.HOME(~) is not set and defaults to e.g./home/[username]or/or/nonexistentthat either does not exists or the executing user does not have write permissions.
- Use Python docker 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
wheelarchives for the platform in the builder stage, and install the platform specific generated wheel packages in the final stage. - Set appropriate PlatformIO and ESPHome environment variables to store projects in
/configand dynamic and temporary content in/cachevolumes. - Refer to
Dockerfilefor container details. - Refer to
BuildDockerPush.ymland for pipeline details.
The included Dev Container can be used for ESPHome Python or PlatformIO C++ debugging in VSCode.
Detailed debug setup details are beyond the scope of this project, refer to my ESPHome-Config project for slightly more complete debugging setup instructions.
- ESPHome's
DockerfileinstallsLIB_DEPSandBUILD_DEPS, that should not be required when installing usingwheel, right? - Using unversioned base Python docker images will use the current released version of Python, and may not always be compatible with ESPHome.
- Alpine uses
muslnotglibc,gcompatis required for PIO and tools that do not have nativemuslsupport. - Track open PR for a general
LOG_LEVELconfiguration vs. usingESPHOME_VERBOSE. - Chance of a version mismatch when tagging the docker image with the current ESPHome version vs. the version actually installed when building the image.