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.4:
- Removed custom handling for
ESPHOME_VERBOSE
enabling--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:gid
notation, 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
user
option will run under defaultroot
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 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) : Useping
instead ofmDNS
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 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 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
# /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$
- 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 PlatformIOgloballib_dir
option to/piolibs
./piolibs
is not mapped to an external volume./piolibs
has default permissions and requiresroot
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 usingpio 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 changespio_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"
, andPLATFORMIO_CACHE_DIR="${pio_cache_base}/cache"
is explicitly set as child directories ofpio_cache_base
.- It is simpler to set
PLATFORMIO_CORE_DIR
PlatformIOcore_dir
option, and not settingPLATFORMIO_PLATFORMS_DIR
platforms_dir
,PLATFORMIO_PACKAGES_DIR
packages_dir
, andPLATFORMIO_CACHE_DIR
cache_dir
options, that are by default child directories ofcore_dir
.
- The presence of a
/build
directory sets theESPHOME_BUILD_PATH
environment variable, that sets theCONF_BUILD_PATH
ESPHomebuild_path
option, the default is/config/.esphome/build
.- The directory presence detection could override an explicitly set
ESPHOME_BUILD_PATH
option.
- The directory presence detection could override an explicitly set
ESPHOME_DATA_DIR
can be used to set the ESPHomedata_dir
intermediate build output directory, the default is/config/.esphome
, or hardcoded to/data
for the HA addon image.PLATFORMIO_CORE_DIR
PlatformIOcore_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.
- 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 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.
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.