やってみた 2026年7月14日

最新のHome Assistant CoreをPython3.14のslimコンテナにpipで入れてみたら、UIが出るまで沼だった

XECIN PythonHome AssistantDockerセルフホスト

GitHubのトレンドを眺めていたら、home-assistant/core が上のほうに来ていました。スター9万近い有名どころなので今さら説明する話でもないんですが、自分はいつも「Home Assistant OS を丸ごと焼く」やり方でしか触ったことがなくて、Coreだけをpipで入れるとどうなるのか、実はちゃんとやったことがなかったんですよね。

公式ドキュメントを見ると Home Assistant Core は pip install homeassistant して hass と打つだけ、と書いてあります。ラズパイでも動くくらいなので軽いはず。じゃあ使い捨てのコンテナに放り込んで、Webの初期設定画面が出るところまで見てみよう、という軽い気持ちで始めました。

結論から言うと、UIが出るまでにけっこう沼りました。しかもハマりどころが全部きれいに一本の線で繋がっていて、個人的にはそこが面白かったので、順番に残しておきます。

試した環境

  • ホストはWindows + Docker Desktop、検証は使い捨ての python:3.14-slim コンテナの中だけ
  • コンテナ内: Python 3.14.6 / pip 26.1.2
  • 対象: homeassistant==2026.7.2(このとき最新のリリース)

Home Assistant Core は requires-python >=3.14.2 になっていて、思ったよりずっと攻めたバージョン要求でした。なので素直に python:3.14-slim を使っています。「3.14でwheelが揃ってなくてビルドで死ぬのでは」と身構えたんですが、そこは杞憂でした。

$ pip install --no-cache-dir "homeassistant==2026.7.2"
...
Successfully installed homeassistant-2026.7.2 aiohttp-3.14.1 SQLAlchemy-2.0.51 ...
=== install elapsed: 32s ===

32秒。C拡張の PyRIC だけソースからビルドされましたが一瞬で、あとは全部wheelでした。ここまでは拍子抜けするほど順調です。

ただ、Successfully installed ... の一覧をよく見ると、home-assistant-frontend(Web UIの本体)が入っていない。ここが後で効いてきます。pip install homeassistant は本当にコア部分だけで、frontendや各連携の依存は「初回起動時にhass自身がその場でインストールする」設計なんですよね。知ってはいたつもりですが、改めて挙動を見ると面白い。

初回起動でいきなりrecovery modeに落ちる

hass を起動して、ホストから http://127.0.0.1:<公開ポート>/ を叩いてみます。ところが、いつまで待っても 404 が返ってくる。ログを見に行くと、こうなっていました。

[homeassistant.bootstrap] Home Assistant initialized in 6.56s
[homeassistant.components.http] Now listening on port 8123
...
[homeassistant.setup] Error during setup of component frontend: No module named 'hass_frontend'
[homeassistant.bootstrap] Detected that frontend did not load. Activating recovery mode

「6.56秒で初期化してポート8123でlistenした」と言っているのに、frontendが No module named 'hass_frontend' で落ちて recovery mode に入ってしまっている。だから / は404。

不思議だったのが、pip show home-assistant-frontend を打つとちゃんと Version: 20260624.5 と出るんです。パッケージ自体は(起動中にhassが /root/.local に入れていた)。それなのにimportできない。

タネはこれでした。hassが動いている最中に frontend を ~/.local へインストールしても、すでに起動しているそのプロセスからは import hass_frontend できない(起動時のsys.pathに載っていないタイミングで取りに行ってしまう)。パッケージは物理的には存在するのにインポートに失敗し、HAは「frontendが無い」と判断してrecovery modeへ、というわけです。

同じログに、もう一つ不穏な行がありました。

error: command 'gcc' failed: No such file or directory
Unable to install package pymicro-vad==1.0.1
Unable to install package pyspeex-noise==1.0.2
[homeassistant.setup] Setup failed for 'cloud': Requirements for assist_pipeline not found

slimイメージには gcc が無いので、音声まわり(assist_pipeline)のC拡張がビルドできず、cloud のセットアップも巻き添えで失敗しています。この時点では「音声機能は使わないしいいか」と軽く流したんですが、これが後で刺さります。

一度落として立て直すと、今度はUIが出る

frontendの依存は初回起動時にもう ~/.local へ入り終わっています。ということは、hassを一度止めてもう一度起動すれば、今度は最初から hass_frontend を取り込めるはず。試すと当たりでした。

$ hass -v      # 2回目の起動
...
/ -> 302
/onboarding.html -> 200

/ が302で /onboarding.html へ飛ぶようになりました。ブラウザで開くと、ちゃんと初期設定画面(オンボーディング)が出ます。ホスト側のChromeのロケールを見てか、最初から日本語でした。

Home Assistantのオンボーディング初期画面。「ようこそ!」の見出しと「私のスマートホームを作成」ボタンが日本語で表示されている

ここから先は普通にウィザードが進みます。ユーザー作成の画面でアカウントを作り、

ユーザー作成フォーム。名前・ユーザー名・パスワードの入力欄が並ぶ

そのあとは「自宅の場所(LeafletのOSM地図)」→「国(日本を選択)」→「匿名の分析データを送るか(今回は全部オフ)」→「完了」と進んで、進捗バーが100%になりました。ここまでは、拍子抜けするくらいスムーズです。

ダッシュボードが「Loading data」から進まない

「完了」を押すとダッシュボード(/)に飛ぶんですが……画面が 「Loading data」から一向に進まない。リロードしても、ブラウザを開き直しても同じ。アプリの殻は出ているのにデータが来ない、という一番モヤモヤするやつです。

バックエンドのログを見て、ようやく腑に落ちました。

[homeassistant.components.websocket_api.http.connection] Error handling message:
  Unknown error (unknown_error) Demo User from 172.17.0.1
  ...
  File ".../assist_pipeline/audio_enhancer.py", line 8, in <module>
    from pymicro_vad import MicroVad
ModuleNotFoundError: No module named 'pymicro_vad'

フロントが起動時に投げるWebSocketメッセージの処理の中で、assist_pipelineaudio_enhancer.pypymicro_vad をimportしようとして落ちている。そう、最初に「音声は使わないしいいか」と流した、gccが無くてビルドできなかったあのモジュールです。

assist_pipelinedefault_config に含まれているので、音声を一切使うつもりが無くても初期状態で有効になっていて、フロントの初期ロードがそこに触れた瞬間に毎回エラーになる。結果、ダッシュボードのデータ取得が完了せず「Loading data」で止まる。「音声機能が無効になるだけ」では済まず、UIごと固まるのが誤算でした。

gccを入れて、最後はlibstdc++で一悶着

原因がはっきりしたので、素直に gccbuild-essential)を入れて、欠けていた2つのC拡張を自分でビルドします。

$ apt-get install -y build-essential      # gcc 14.2.0、約10秒
$ pip install --user "pymicro-vad==1.0.1" "pyspeex-noise==1.0.2"
Successfully installed pymicro-vad-1.0.1 pyspeex-noise-1.0.2

ビルドは通った。よし、と思って import を確認すると、まだ落ちる。

$ python -c "import pymicro_vad"
ImportError: .../micro_vad_cpp...so: undefined symbol: _ZTVN10__cxxabiv117__class_type_infoE

_ZTVN10__cxxabiv117__class_type_infoE はC++のABIシンボルで、要はC++の標準ライブラリ(libstdc++)がリンクされていない .so になっている、という定番のやつです。今回はコンテナも使い捨てなので、深追いせず LD_PRELOAD で libstdc++ を先読みさせて逃げました。

# ここは正直やっつけ。恒久対応というより「使い捨て環境で先に進むための回避」です
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 hass -v

この状態でhassを立て直したら、WebSocketのエラーがきれいに消えて、ダッシュボードが Loading data を抜けて /home/overview まで来てくれました。

ロードが完了したHome Assistantのオーバービュー画面。「ようこそDemo Userさん」の見出しと、リビングルーム・台所・寝室のエリア、左に設定やエネルギー等のサイドバー

「ようこそDemo Userさん」と出て、リビングルーム・台所・寝室のエリアやサイドバーが並ぶ、見慣れた画面。ここまで来てようやく一息つけました。

つまずきを並べてみると

振り返ると、詰まった3か所は全部「slimイメージにgccが無い」に根っこが繋がっていました。

症状直接の原因今回の対処
初回起動でrecovery mode(/が404)起動中に入れたfrontendを同プロセスがimportできない依存が揃った状態でhassを再起動
ダッシュボードがLoading dataで停止assist_pipelineがpymicro_vadをimportして失敗(gcc無しでビルド不可)build-essentialを入れてビルド
ビルド後もimportがundefined symbolC++拡張がlibstdc++未リンクLD_PRELOADでlibstdc++を先読み(暫定)

試してみての所感

pip install homeassistant が32秒で終わった時点では「なんだ簡単じゃん」と思ったんですが、そのあとが本番でした。とはいえ、詰まった原因はどれも Home Assistant のせいというより、自分が極端に軽いslimイメージを選んだことに由来していて、公式が用意している Home Assistant Container(gccやビルド依存を最初から含むイメージ)を素直に使えば、この沼はほぼ踏まないはずです。今思えば「Coreをslimに手で入れる」という縛りを自分でかけた結果ですね。

学びとして大きかったのは、Home Assistantが依存を起動時に動的インストールする設計だという点。おかげで初回と2回目で挙動が変わるし、default_config が有効な限り「使わないつもりの音声機能」の依存欠けがUI全体を止めうる。ここは動かしてみて初めて体感できました。

自分の使い方としては、ちゃんと運用するなら公式のContainerイメージ一択で、slimに手入れするのは「中で何が起きているか観察する」用途に留めるかな、というのが正直なところ。ここは好みが分かれるところですが、こういう「軽い環境で動かして裏側を覗く」遊びは、たまにやると仕組みの理解がぐっと進むのでおすすめです。

もっと良いやり方(特にlibstdc++まわりのスマートな解決策)があったら教えてください。