fhem / fhem-docker

A basic Docker image for FHEM house automation system, based on Debian Linux.
https://fhem.de/
MIT License
84 stars 27 forks source link
docker-fhem docker-image dockerfile fhem fhem-docker home-automation home-automation-system house-automation

Main branch - Build and Test Development branch - Build and Test


Docker image for FHEM

A Docker image for FHEM house automation system, based on Debian.

Installation

Pre-build images are available on Docker Hub Reccomended pulling from Github Container Registry to allow automatic image for your system.

From Docker Hub

docker pull fhem/fhem:latest

From Github container registry

Image with serval services installed

Updated versions based on

If you are using 3rd Party modules which are not available on the FHEM svn repository, you may need this image, because it has more perl modules preinstalled.

To let this image work correctly, you need as least a FHEM revision 25680 or newer.

Not updated anymore since Jan 2024

Image with perl core services installed

If you are using only modules which are provided via FHEM svn repository, you mostly can use this smaller image.

Not updated anymore since Jan 2024

To start your container right away:

    docker run -d --name fhem -p 8083:8083 ghcr.io/fhem/fhem-docker:4-bullseye

Storage

Usually you want to keep your FHEM setup after a container was destroyed (or re-build) so it is a good idea to provide an external directory on your Docker host to keep that data:

    docker run -d --name fhem -p 8083:8083 -v /some/host/directory:/opt/fhem ghcr.io/fhem/fhem-docker:4-bullseye

You will find more general information about using volumes from the Docker documentation for Use volumes and Bind mounts.

It is also possible to mount CIFS mounts directly.

Access FHEM

After starting your container, you may now start your favorite browser to open one of FHEM's web interface variants like http://xxx.xxx.xxx.xxx:8083/.

You may want to have a look to the FHEM documentation sources for further information about how to use and configure FHEM.

Update strategy

Note that any existing FHEM installation you are mounting into the container will not be updated automatically, it is just the container and its system environment that can be updated by pulling a new FHEM Docker image. This is because the existing update philosophy is incompatible with the new and state-of-the-art approach of containerized application updates. That being said, consider the FHEM Docker image as a runtime environment for FHEM which is also capable to install FHEM for any new setup from scratch.

Customize your container configuration

Performance implications

The FHEM log file is mirrored to the Docker console output in order to give input for any Docker related tools. However, if the log file becomes too big, this will lead to some performance implications. For that reason, the default value of the global attribute logfile is different from the FHEM default configuration and set to a daily file (attr global logfile ./log/fhem-%Y-%m-%d.log).

It is highly recommended to keep this setting. Please note that FileLog are only patched if fhem is fresh installed. Devices might still need to be checked and adjusted manually if you would like to properly watch the log file from within FHEM.

Add custom packages

Since version 4

To extand the image wirh a custom package for example, you have to use standard docker tools.

If you are defining a docker-compose.yml file describing your configuration, then you can add a build definition instead of starting the image from the registry:

With this, you will create a new image, and install any tool which you additional need:

    build:
      context: .
      dockerfile_inline: |
        FROM ghcr.io/fhem/fhem-docker:4-bullseye 
        RUN <<EOF
          LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get update 
          LC_ALL=C DEBIAN_FRONTEND=noninteractive apt-get install -qqy --no-install-recommends <DEBIAN PACKAGENAME>
          LC_ALL=C apt-get autoremove -qqy && LC_ALL=C apt-get clean 
        EOF

        RUN <<EOF
          pip install --no-cache-dir <PIP PACKAGENAME>
        EOF

See more examples in our docker-compose.yml file.

Important: If you need additional Perl CPAN Modules, you must install them directly from CPAN and not via apt!

till version 3 (deprecated)

Don't do this unless you really know what this does! You may define several different types of packages to be installed automatically during initial start of the container by adding one of the following parameters to your container run command:

Directory and file permissions

For security and functional reasons, directory and file permissions for FHEM will be set during every container startup. That means that directories and files can only be opened by members of the $FHEM_GID user group or the $FHEM_UID user itself. Also, the execution bit for files is only kept for a limited set of file names and directories, which are:

Should you require any different permissions, you may read the next section to learn more about how to make any changes using custom pre start script /pre-start.sh or /docker/pre-start.sh.

Make any other changes during container start

In case you need to perform further changes to the container before it is ready for your FHEM instance to operate, there are a couple of entry points for your own scripts that will be run automatically if they are found at the right place. In order to achieve this, you need to mount the script file itself or a complete folder that contains that script to the respective destination inside your container. See Docker documentation about Use volumes and Bind mounts to learn how to achieve this in general.

If something needs to be done only once during the first start of a fresh container you just created, like after upgrading to a new version of the FHEM Docker Image, the *-init.sh scripts are the right place:

If something needs to be done every time you (re)start your container, the *-start.sh scripts are the right place:

Role of the telnet device in FHEM

since version 4

There is no internal use of the telnet device anymore

till version 3 (deprecated)

The Docker container will need to communicate with FHEM to shutdown nicely instead of just killing the process. For this to work properly, a telnet device is of paramount importance. Unless you are using configDB, the container will try to automatically detect and adjust your telnet configuration for it to work. If for any reason that fails or you are using configDB, it is your own obligation to configure such telnet device (define telnetPort telnet 7072). It may listen on the standard port 7072 or can be any other port (see environment variable TELNETPORT to re-configure it).

It is enough for the telnet device to only listen on the loopback device (aka localhost) but it cannot have any password protection enabled for loopback connections. If you require your telnet instance to listen for external connections, it is usually best-practice to set a password for it. In that case, make sure that any allowed device you might have configured for this purpose only requires a password for non-loopback connections (e.g. using attribute globalpassword instead of password - also see allowed commandref). The same applies when using the deprecated attribute password for the telnet device itself (see telnet commandref).

Docker health check control

The image comes with a built-in script to check availability, which communicates with the DockerImageInfo Definition.

If for whatever reason you want to disable checking a specific FHEMWEB instance, you may set the user attribute DockerHealthCheck to 0 on that particular FHEMWEB device.

Note that the health check itself cannot be entirely disabled as it will ensure to notify you in case of failures, hindering proper shutdown of FHEM when triggered by Docker or OS shutdown procedure.

Map USB devices to your container

  1. Find out the USB device path/address from your Docker host machine first:

    lsusb -v | grep -E '\<(Bus|iProduct|bDeviceClass|bDeviceProtocol)' 2>/dev/null
  2. You may then derive the device path from it and add the following parameter to your container run command:

    --device=/dev/bus/usb/001/002

Tweak container settings using environment variables

Further tweaks for your FHEM configuration

Connect to Docker host from within container

If you would like to connect to a service that is running on your Docker host itself or to a container that is running in host network mode, you may use the following DNS alias names that are automatically being added to /etc/hosts during container bootup:

That is, if you did not configure those in your local DNS, of course.

In case the container is running in host network mode, the host IP address will be set to 127.0.127.2 as an alias for 'localhost'. That means a service you would like to reach needs to listen on the loopback interface as well. If a service you would like to reach is only listening on a particular IP address or interface instead, you need to set the environment variable DOCKER_HOST to the respective IP address as there is no way for the FHEM Docker Image to automatically detect what you need. When running in host network mode, the gateway will reflect your actual network segment gateway IP address.

Also, for host.docker.internal, the SSH host key will automatically be added and updated in /opt/fhem/.ssh/known_hosts so that FHEM modules and other scripts can automatically connect without any further configuration effort. Note that the SSH client keys that FHEM will use to authenticate itself are shown as readings in the DockerImageInfo device in FHEM. You may copy & paste those to the destination host into the respective destination user home directory with filename ~/.ssh/authorized_keys.

If for some reason the host details are not detected correctly, you may overwrite the IP addresses using environment variables (see DOCKER_HOST and DOCKER_GW above).

Adding Git for version control of your Home Automation Docker containers

Prerequisites on your Docker host:

  1. Ensure docker-compose is installed: See Install Docker Compose
  2. Ensure Git command is installed, e.g. run sudo apt install git

Follow initial setup steps:

  1. Put docker-compose.yml and .gitignore into an empty sub-folder, e.g. /docker/home

    sudo mkdir -p /docker/home
    sudo curl -fsSL -o /docker/home/docker-compose.yml https://github.com/fhem/fhem-docker/raw/master/docker-compose.yml
    sudo curl -fsSL -o /docker/home/.gitignore https://github.com/fhem/fhem-docker/raw/master/.gitignore

    Note that the sub-directory "home" will be the base prefix name for all your Docker containers (e.g. resulting in home_SERVICE_1). This will also help to run multiple instances of your Stack on the same host, e.g. to separate production environment in /docker/home from development in /docker/home-dev.

  2. Being in /docker/home, run command to start your Docker stack:

    cd /docker/home; sudo docker-compose up -d

    All FHEM files including your individual configuration and changes will be stored in ./fhem/ . You may also put an existing FHEM installation into ./fhem/ before the initial start, it will be automatically updated for compatibility with fhem-docker. Note that if you are using configDB already, you need to ensure Docker compatibility before starting the container for the very first time (see DOCKER_* environment variables above).

  3. Create a local Git repository and add all files as an initial commit:

    cd /docker/home
    sudo git init
    sudo git add -A
    sudo git commit -m "Initial commit"

    Run the following command whenever you would like to mark changes as permanent:

    cd /docker/home; sudo git add -A; sudo git commit -m "FHEM update"

    Note: This will also add any new files within your whole Docker Stack outside of the ./fhem/ folder. Please see Git documentation for details and further commands.

  4. Optional - Add remote repository for external backup. It is strongly recommended to have your external repository set to private before doing so:

    sudo git remote add origin git@github.com:user/repo.git
    sudo git push --force --set-upstream origin master

    Note that after updating your local repository as described above, you also want to push those changes to the remote server:

    cd /docker/home; sudo git push

    To restore your Docker Stack from remote Git backup on a fresh Docker host installation:

    sudo mkdir -p /docker
    cd /docker; sudo git clone git@github.com:user/repo.git
    cd /docker/home; sudo docker-compose up -d

Testing the Image itself in a container

Basic testing of the image is done in the pipeline. The pipeline will start a container and verify that the health check reports the container is alive.

The bash scripts inside the container, are tested via bats:

To run the test, build the image with the specific target:

docker build --rm --load -f "Dockerfile-bullseye" -t fhemdocker:test --target with-fhem-bats "."

Then this image, can be used to start a new container and running bats inside the container. docker run -it --rm -v "${PWD}/src/tests/bats:/code" fhemdocker:test .

A needed perl module is missing

If you are running a 3rd party module, advice the maintainer to this description:

During docker build, repositorys are searched by topics and content in the readme.md file.
If the build finds your repository, it will check automatically, what perl modules are needed.
Modules wich are found will be installed via cpan in the resulting docker image.
This allows users of the docker image to use your module. 

Add the topic 'fhem' and 'perl' and provide an instruction in your readme.md with 
instruction how to use update add / update all to install your module.