DEV Community

jeikabu
jeikabu

Posted on • Originally published at rendered-obsolete.github.io on

Addendum- Migrating to Jetson Nano and Docker

After installing Rhasspy on a Raspberry Pi 3B and seeing it struggle, I decided to move everything to a beefier Jetson Nano. While I was at it, took the opportunity to switch to docker to avoid some of the systemd wrangling.

Rhasspy

Rhasspy provides speech recognition, speech-to-intent, and text-to-speech. Installation is mostly the same as before:

docker run -d -p 12101:12101 \
      --name rhasspy \
      --restart unless-stopped \
      -v "$HOME/.config/rhasspy/profiles:/profiles" \
      --device /dev/snd:/dev/snd \
      --device /dev/bus/usb:/dev/bus/usb \
      synesthesiam/rhasspy-server:latest \
      --user-profiles /profiles \
      --profile en
Enter fullscreen mode Exit fullscreen mode

With the Nano, I needed to add --device /dev/bus/usb:/dev/bus/usb so USB devices like ReSpeaker are also accessible inside the container.

Home Assistant

Home Assistant (Hass) is the “smart home” platform and among other things provides: intent handling, automation, location-based services, etc. Hass has docker installation instructions:

docker run --init -d --name="home-assistant" -e "TZ=America/New_York" -v /PATH_TO_YOUR_CONFIG:/config --net=host homeassistant/home-assistant:stable
Enter fullscreen mode Exit fullscreen mode

We’ll change this to:

docker run -d -p 8123:8123 \
    --name hass \
    --restart unless-stopped \
    -v $HOME/.homeassistant:/config \
    -e "TZ=Asia/Nicosia" \
    homeassistant/home-assistant:stable
Enter fullscreen mode Exit fullscreen mode
  • Shorten the name to “hass”, just because typing “home-assistant” is tedious
  • unless-stopped restart policy- the docker daemon will automatically (re-)start it
  • $HOME/.homeassistant like when doing manual install
  • Value after TZ= with the appropriate name from “tz database” time zones
  • host networking on Linux means we don’t need to forward any ports for the frontend like -p 8123:8123, but doesn’t seem to work with docker network (see below)

Integration

Both Hass and Rhasspy are running in containers, but they can’t talk to eachother yet. The “old” way to connect two containers was to use --link. The new way is using “networks”. First, create a network called “smart-home”:

docker network create smart-home
Enter fullscreen mode Exit fullscreen mode

To each of the docker run commands we then add --network smart-home. For Hass, we also remove --net=host and add -p 8123:8123 (for the web frontend). Restart the containers and we can confirm that Rhasspy can talk to the “hass” container:

docker exec -it rhasspy bash
# Install ping (or some other command)
apt install -y inetutils-ping
ping hass
Enter fullscreen mode Exit fullscreen mode

Now, when connecting Rhasspy to Hass, for Hass URL use http://hass:8123.

Start-Up

With everything on docker we don’t really need systemd to start the individual services, just the docker daemon itself.

We supply both our containers with --restart unless-stopped so the daemon will launch them as soon as it starts (unless we manually stop them). We just need to make sure the docker daemon starts at boot:

sudo systemctl enable docker
sudo reboot

# Wait for it to reboot

ssh jetson-nano.local
# Try Rhasspy TTS to make sure Rhasspy is running:
curl -X POST -d "hello world" http://localhost:12101/api/text-to-speech
Enter fullscreen mode Exit fullscreen mode

And docker ps should output something similar to:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e797909decb6 synesthesiam/rhasspy-server:latest "/run.sh --user-prof…" 32 hours ago Up About a minute 0.0.0.0:12101->12101/tcp rhasspy
06cf50964e98 homeassistant/home-assistant:stable "/bin/entry.sh pytho…" 33 hours ago Up About a minute 0.0.0.0:8123->8123/tcp hass
Enter fullscreen mode Exit fullscreen mode

Be careful about using docker ps to verify everything is starting at boot. If the daemon didn’t start, docker ps will start it- along with the containers.

docker-compose

With multiple containers and so many options things are starting to get hairy. We can reign things in with docker compose. Create docker-compose.yml with mostly the same contents as the docker run commands:

version: '3'
services:
    hass:
        image: "homeassistant/home-assistant:stable"
        restart: unless-stopped
        volumes:
            - "$HOME/.homeassistant:/config"
        ports:
            - "8123:8123"
        environment:
            - TZ=Asia/Nicosia
    rhasspy:
        image: "synesthesiam/rhasspy-server:latest"
        restart: unless-stopped
        volumes:
            - "$HOME/.config/rhasspy/profiles:/profiles"
        ports:
            - "12101:12101"
        devices:
            - "/dev/snd:/dev/snd"
            - "/dev/bus/usb:/dev/bus/usb"
        command: --user-profiles /profiles --profile en
Enter fullscreen mode Exit fullscreen mode

We don’t need the --network option because the desired networking is implicitly provided by compose.

Install docker compose and launch our containers:

# Install pre-requisites
sudo apt install -y python-pip libffi-dev libssl-dev
# Install docker-compose
sudo pip install docker-compose
# Start containers. `-d` for detached mode
docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

If you check Rhasspy, you may see the following problem:

HomeAssistantIntentHandler  Can't contact server    Unable to reach your Home Assistant server at http://hass:8123. Is it running?
Enter fullscreen mode Exit fullscreen mode

Rhasspy starts before Hass is ready and listening. If you test further you’ll find that it has already retried and connected. This behavior aligns with the “docker ethos” of fault-tolerant containers. Should it really bother you, feel free to investigate the rickety world of container dependencies:

Top comments (0)