Home Assistant in Docker #3: docker-compose.yml for Home Assistant and MariaDB explained

Home Assistant in Docker #3: docker-compose.yml for Home Assistant and MariaDB explained

In the current post series, I’m describing the path I took from a regular Home Assistant setup on Home Assistant Blue to a home server with Docker and various software. Assuming we already have ODROID-N2+ with Debian Buster and Docker setup, our next step would be bringing Home Assistant with MariaDB to life.

Previous posts in series:

Docker Compose allows us to define and run multi-image applications with one simple YAML file and one command. Home Assistant is sure could be a multi-image application, because at least we need a good solution for history and stats. Later on, we will add ESPHome, Zigbee2MQTT, and other services, but in today’s post let’s focus on a Home Assistant itself.

I don’t want to drop my docker-compose.yml here and mind my own business. There are a lot of examples around the Internet, but most of them have questionable configuration entries. I want to explain, why and when you need to use one or another docker settings.

Host network mode for example. Official Home Assistant documentation suggests using network_mode: host not mentioning, that it would be a good practice only when your Home Assistant is the only container in your smart home setup. When we have several containers that should communicate with each other, we sure need to use network_mode: bridge. First of all, it would follow official docker docs. Second, it will allow us to use container names instead of IP addresses (that could be changed) when integrating our additional services into HA.

Also, why Home Assistant needs a privileged mode? Exposing your operating system to a service that could potentially be accessed from the outside of your router sounds like a very bad idea. Not gonna lie, this would be the easiest way to start using Home Assistant in a Docker: host network mode and privileged execution. But you can avoid potential risks and issues in the future just by understanding slightly more complex configuration options.

The most comfortable way to edit files, execute commands, and do any other things with your headless (which means a computer without a monitor) server is to use Visual Studio Code with the “Remote – SSH” plugin.

docker-compose.yml

Now it is time to drop my docker-compose.yml and describe some more things on a working example:

version: "3"

name: homeassistant_stack

services:

  mariadb:
    image: mariadb
    container_name: mariadb
    restart: unless-stopped
    hostname: mariadb
    ports:
      - 3306:3306
    environment:
      MARIADB_ROOT_PASSWORD: *******
      MARIADB_DATABASE: homeassistant
      MARIADB_USER: my_own_house
      MARIADB_PASSWORD: *******

  homeassistant:
    container_name: homeassistant
    image: "ghcr.io/home-assistant/home-assistant:latest"
    volumes:
      - /root/homeassistant/config:/config
      - /root/homeassistant/share:/share
    environment:
      - TZ=Europe/Kyiv
    ports:
      - 8123:8123  
    devices:
      - /dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0:/dev/ttyACM1
    depends_on:
      - "mariadb"
    restart: unless-stopped

As I’m using my server as a root user, my home directory is /root. I’ve placed docker-compose.yml in /root and have a separate folder for each smart home stack service. I’ve created the/root/homeassistant/config directory for Home Assistant configuration, and /root/homeassistant/share for the HA share folder. “share” folder is not necessary. I created it only because I had an integration that stores a file in the “share” folder. You can create “media” and any other folders the same way if you need it.

So, obviously, these lines in homeassistant service are for exposing host folders to a Home Assistant container:

volumes:
  - /root/homeassistant/config:/config
  - /root/homeassistant/share:/share

Let’s get back to the mariadb service for now. The ports allow us to expose network ports for inbound connections. 3306 is a standard MariaDB port. HA will use it for connection.

MARIADB_ROOT_PASSWORD is a root password for your MariaDB installation. MARIADB_DATABASE variable would force MariaDB to create a database with a given name upon a first start, assigning MARIADB_USER with MARIADB_PASSWORD to it. You will need this data for the Home Assistant configuration later.

Going back to the homeassistant service, let us look to other options:

environment:
  - TZ=Europe/Kyiv

You should replace “Europe/Kyiv” with your timezone name taken from the “TZ database name” column in the table here.

image: "ghcr.io/home-assistant/home-assistant:latest"

This will pull the latest stable Home Assistant version from packages on GitHub but only when you’ll tell Docker Compose to do so. Stopping and starting the container will not pull any images.

To get more control over Home Assistant versions you can replace latest with a given package tag found here. For example:

image: "ghcr.io/home-assistant/home-assistant:2022.12.7"

Now you’ll be sure that Home Assistant will not be updated until you update your docker-compose.yml.

ports:
  - 8123:8123

This is the only port you need to expose to make Home Assistant work even through Nabu Casa Cloud.

devices:
  - /dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0:/dev/ttyACM1

This is how you allow a given hardware from your host machine to be used in Home Assistant. /dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0 – is a GSM modem, connected to my host machine. /dev/ttyACM1 – is a path to a device I’m using in Home Assistant when adding GMS modem integration.

depends_on:
  - "mariadb"

These lines will tell Docker that when the Home Assistant container is starting, it should wait till MariaDB will be up first. Otherwise Recorder component in Home Assistant will fail to start and you’ll get Home Assistant without entities history.

First start

Now it is time to fire things up with:

docker compose up -d

You should execute this command in the same folder where your docker-compose.yml is placed.

This will download all the necessary data to start your Home Assistant. Once done, you should be able to navigate to your Home Assistant frontend using your server’s IP address and port 8123. For example “http://192.168.90.23:8123” from inside your local network.

HA config

Now we need to configure the recorder component in the newly created configuration.yaml file. In my case, it is created under /root/homeassistant/config:

recorder:
  db_url: mysql://my_own_house:*******@mariadb/homeassistant?charset=utf8mb4
  auto_purge: true
  purge_keep_days: 10

The database URL is consist of mysql://MARIADB_USER:MARIADB_PASSWORD@mariadb/MARIADB_DATABASE?charset=utf8mb4

“mariadb” in the URL is the name of our service from docker-compose.yml.

Stopping, starting and restarting

Now we need to restart Home Assistant for changes to apply. We can easily do this with:

docker compose restart homeassistant

Sure you can do the same from Home Assistant UI as usual.

While you have several services defined in your docker-compose.yml

docker compose restart

without any additional parameters will restart all services. Also, you can just stop any container or start it:

docker compose start mariadb

Or stop it all:

docker compose stop

Updating

Not sure why you’ll want to update your MariaDB container while it works, but updating Home Assistant is important.

If you are using latest tag for your homeassistant service image:

image: "ghcr.io/home-assistant/home-assistant:latest"

to update it to a latest stable version you’ll need to:

docker compose pull homeassistant

and then

docker compose up -d homeassistant

That’s it.

Don’t forget to change the image tag if you are not using latest.

Next posts in series: