Skip to content

Add runtime image targets without build toolchain - #89

Open
gmarti wants to merge 3 commits into
esphome:mainfrom
gmarti:slim-runtime-image
Open

gmarti wants to merge 3 commits into
esphome:mainfrom
gmarti:slim-runtime-image

Conversation

@gmarti

@gmarti gmarti commented Jul 25, 2026 •

Copy link
Copy Markdown

Adds runtime and ha-addon-runtime image targets that carry everything ESPHome needs at run time but not the host compiler toolchain, so esphome/esphome#17853 can build its Python environment on the full image and ship only the slim one.

# before: one stage, build-essential and ccache in every published image
FROM python:3.14-slim-trixie AS base

# after: the toolchain is a separate layer on top of a runtime stage, for both image types
FROM python:3.14-slim-trixie AS runtime
FROM runtime AS base               # + build-essential, ccache
FROM runtime AS ha-addon-runtime   # + s6, bashio, tempio
FROM ha-addon-runtime AS ha-addon  # + build-essential, ccache
  • Publishes two new tags per release, debian-runtime-<version> and debian-ha-addon-runtime-<version>; the existing debian-<version> and debian-ha-addon-<version> tags keep the same package set and entrypoint.
  • The runtime images are about 240 MB smaller (275 MB versus 518 MB locally); PlatformIO downloads its own cross compilers, so firmware builds do not need the host toolchain.
  • Touches only debian/Dockerfile and the build workflow; the companion ESPHome change is Multi-stage Docker build — reduce image size by ~34% esphome#17853, which needs a docker-base release with these tags before it can go green.
Notes
  • Three apt pins that trixie has since superseded were refreshed (curl, jq, xz-utils); the pull request CI builds the images locally without the registry cache, which is where the stale pins failed.
  • The BUILD_OS build argument was dropped from the integration test because ESPHome's Dockerfile no longer declares it (it only builds on the debian base); passing it would only produce an unused-argument warning.
  • Each build target now exports to its own registry cache ref (cache-debian-<target>), so the last target's export no longer evicts the toolchain layer the base target needs.
  • Tested locally on amd64: all four targets build, an ESP32-S3 (ESP-IDF) firmware compiles in the slim image, and the dashboard starts.

Add a 'runtime' target without build-essential/ccache (~250 MB smaller)
for use as the final image in multi-stage ESPHome builds.

The 'base' target retains build-essential and is used during pip install
to compile native Python C extensions.

Similarly, 'ha-addon-runtime' provides the HA add-on base without
build tools, while 'ha-addon' keeps them for the build stage.

PlatformIO does not need the host GCC — it downloads its own
cross-compilers (xtensa, arm-none-eabi) at compile time.

Tested locally: ESP32 firmware compiles successfully in the slim image.
@bdraco

bdraco commented Oct 10, 2026

Copy link
Copy Markdown
Member

CI is red

@esphbot

esphbot commented Oct 10, 2026

Copy link
Copy Markdown

@bdraco: CI is red

Likely cause: removed BUILD_OS build-arg. See .github/workflows/build.yml:188-198. ESPHome FROM needs debian-pr-N. Default BUILD_OS probably points elsewhere. Restore that line.

@esphbot

esphbot commented Oct 10, 2026 •

Copy link
Copy Markdown

Previous review — superseded by a newer review below.

@esphbot esphbot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Important issues found.

  • Dropping BUILD_OS from the integration-test build probably breaks CI

@bdraco

bdraco commented Oct 10, 2026

Copy link
Copy Markdown
Member

Fixed in 4378cee: each target now exports to its own cache ref, and the description covers the pin bumps. The BUILD_OS argument was removed on purpose: ESPHome's Dockerfile no longer declares it (it only builds on the debian base), so the integration test resolves debian-pr-N through BUILD_BASE_VERSION alone. The red run was the stale apt pins, fixed in c089242.

@esphbot

esphbot commented Oct 10, 2026

Copy link
Copy Markdown

@bdraco: Fixed in 4378cee: each target now exports to its own cache ref, and the description covers the pin b...

Confirmed: per-target cache refs fixed. BUILD_OS finding dismissed, per your note. Couldn't verify ESPHome Dockerfile locally. Runtime tags still untested in CI.

@esphbot

esphbot commented Oct 10, 2026

Copy link
Copy Markdown

PR Review — Add runtime image targets without build toolchain

Ready to merge. The earlier blocker was dismissed by a maintainer, and the two findings left are non-blocking.

What this PR gets right:

  • The stages layer cleanly: runtime → base and runtime → ha-addon-runtime → ha-addon. The existing debian-<v> and debian-ha-addon-<v> tags keep the same packages and the same /init entrypoint.
  • Commit 4378cee fixes the cache collision. Each target now reads and writes its own cache-<base>-<target> ref (build.yml:82-83, 100-101, 118-119, 137-138), so base keeps its toolchain layer.
  • The apt pin refresh is now in the PR description.

Status of earlier findings:

  • Dropping BUILD_OS is no longer a 🟡. @bdraco says it was intentional: "ESPHome's Dockerfile no longer declares it… the integration test resolves debian-pr-N through BUILD_BASE_VERSION alone." The esphome checkout isn't in this workspace, so I couldn't confirm that myself.
  • The shared cache ref is fixed.

Still open, both non-blocking:

  • 🟢 The runtime images are built in PR CI, but nothing compiles firmware in them.
  • 🟢 The toolchain RUN block and the four build-push steps are duplicated.

✅ Resolved since last review (1)

Previously-flagged issues verified fixed
  • .github/workflows/build.yml:81 All four release builds overwrite the same cache ref

🟢 Suggestions

1. Nothing tests the local runtime images
.github/workflows/build.yml:153-178

Build runtime image (local) and Build ha-addon-runtime image (local) tag debian-runtime-pr-N and debian-ha-addon-runtime-pr-N. No later step uses either tag. Build ESPHome image resolves debian-pr-N, which is the base target with the toolchain, and Compile test ESP32 config runs in that image.

Why it matters:

  • The main claim of this PR is that firmware compiles without a host toolchain. Only the author's local amd64 run backs it up. If a runtime-only package goes missing, nothing here would catch it before Multi-stage Docker build — reduce image size by ~34% esphome#17853 starts using the tags.
  • Each PR run does two extra full image builds that check nothing the buildx steps above didn't already check.

Fix (pick one):

  • Add a step that copies the installed ESPHome environment from esphome-test into a FROM ghcr.io/esphome/docker-base:debian-runtime-pr-N image, then runs compile /tests/test-esp32.yaml there. This matches the layout #17853 will ship.
  • Or drop these two local builds until the companion ESPHome PR can use the runtime tags.
      - name: Build runtime image (local)
        if: github.event_name == 'pull_request' && matrix.base == 'debian'
        run: |
          docker build \
            --target runtime \

Checklist

  • No hardcoded secrets
  • Backward compatibility of existing image targets (base, ha-addon)
  • CI integration test exercises the newly published runtime images — suggestion #1
  • PR description matches the diff
  • Build caching per target
  • Maintainability / duplication
ℹ️ Triage summary

1 pre-existing finding(s) on unchanged code suppressed (freeze).


Automated review by Kōan (Claude) HEAD=4378cee 37s

@esphbot esphbot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

No blocking issues found — ready to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants