Please see the Docker Installation Page and DockerHub Readme for the most recent instructions.
Update Jan 30, 2018
Upgrades are now handled by the container.
Update Jan 20, 2017
This update is an almost complete rewrite of the tutorial to comply with recent changes to OH and in preparation of moving the tutorial to the official docs.
Update Nov. 12
The latest build as of Nov. 10 #579 reworks the locations of a lot of config files moving them from runtime/karaf/etc and rutime/etc to userdata/etc. You will likely want to let OH recreate the userdata folder to make sure the userdata/etc folder gets fully populated. When you do, you will have to go through any steps you initially did when first setting it up such as adding the Serial connection for zwave and accepting auto-discovered Items once again.
The big change to the instructions below is the volume to mount the config file is no longer needed.
An alternative upgrade path could be (though Iâve not tested it) is to edit the Docker command to not mount userdata, start the container, and copy the contents of /openhab/userdata/etc out of the container into your host so you have all the needed files.
Failing to do either approaches above will result in an OH that will not load complaining of errors loading/parsing files in etc.
This tutorial is less a step-by-step tutorial and more of a set of issues and gotchas you may encounter running openHAB 2âs official Docker image. For installation instructions please see the official openHAB 2 Docker image on DockerHub.
#Why Docker?
Docker is the most popular among a collection of tools that provide containerization. Containerization allows one to run a server in its own isolated environment without the overhead of running a full virtual machine.
There are several reasons one would want to run openHAB in a Docker container. These include:
- easily test out different versions
- run multiple instances side by side
- easily map the OH ports to other ports without modifying configs
- isolate OH from the rest of your server environment (e.g. configure the containerâs networking so the only way it can be accessed is through a reverse proxy)
- orchestration and automated deployment of OH and related servers
However, this flexibility comes at a cost. For example, because openHAB is running in its own container with only enough installed to run openHAB, the Exec binding is very likely to be useless to you because the container will not have access to the programs and files you need.
About the openHAB installed in the Image
Inside the Docker Image, openHAB is installed to /openhab
. The install is a manual installation so all of the files are located here. This is also set as the home directory of the openhab
user.
The Image has a very minimal installation of Linux with no services running and just enough installed to allow openHAB to run.
At the time of this writing, the official image uses the latest snapshot version of openHAB 2.
Obtaining the Official image from DockerHub
The Docker Hub has the basic information necessary to acquire and run the Docker image. Please review those instructions before continuing to select the correct image for your machine and download the image.
Create the openhab user
Just because one is running in an isolated container does not mean running as root is recommended. So first create an openhab
user configured to be a system user with no home and no shell. This can be done on Ubuntu and Raspbian with the command:
sudo useradd -r -s /sbin/nologin openhab
Add your regular user to the openhab
group.
usermod -a -G openhab <user>
Create the openHAB conf, userdata, and addon directories
These directories will be mounted into the running Docker container and are where the configurations and persistence data will be stored. Note that the software running inside a Docker container cannot follow the symbolic links located in a mounted volume. Make sure the openhab
user owns these directories.
mkdir /opt/openhab
mkdir /opt/openhab/conf
mkdir /opt/openhab/userdata
mkdir /opt/openhab/addons
chown -R openhab:openhab
Running the Container as a Service Managed by Docker
Services can be run an maintained on a Linux machine one of two ways, using Docker or using the systemâs built in service management (e.g. systemd). If using docker to manage the service, run the following command:
docker run \
--name openhab \
--net=host \
-v /etc/localtime:/etc/localtime:ro \
-v /etc/timezone:/etc/timezone:ro \
-v /opt/openhab/conf:/openhab/conf \
-v /opt/openhab/userdata:/openhab/userdata \
-v /opt/openhab/addons:/openhab/addons\
-d \
--user=<uid> \
--restart=always \
openhab/openhab:amd64
Where <uid>
is the user ID number for the openhab
user which you can obtain using the command id openhab
and <arch>
is the architecture of your system. It is important that ID number is passed in as the ID for the openhab
user inside the container will not match the id of the user on your host system and file permissions may be a bit odd (e.g. why does www-data own my openHAB config files?)
See below for an explanation of the fields passed to docker.
Once it successfully runs (it should be listed with a CREATED time that does not include ârestartingâ when running docker ps
.
To stop the service run docker stop openhab
.
To restart the service run docker restart openhab
To start the service run docker start openhab
To change the runtime parameters stop the container then execute the long command above with the new parameters.
Additional fields that may be required:
-
-v /opt/openhab/.java:/openhab/.java
if using the Nest binding -
--device=/dev/ttyUSB0
if using a USB dongle such as a zwave controller
Running the container as a service
If running on a Systemd based Linux distro (Ubuntu 16.1 to be specific). The following openhab2.service file will start a new openHAB 2 container every time it starts the service and destroy that container when the service stops. What that means is any data that you want to preserve between restarts of openHAB 2 (e.g. configuration, databases, etc.) must be mounted from your host file system into the container.
Creating a new container on every run greatly simplifies the upgrade and update process. It also ensures that you start with a fresh install every time you run which can avoid some problems.
[Unit]
Description=openHAB 2
Requires=docker.service
After=docker.service
[Service]
Restart=always
ExecStart=/usr/bin/docker run --name=%n --net=host \
-v /etc/localtime:/etc/localtime:ro \
-v /etc/timezone:/etc/timezone:ro \
-v /opt/openhab/conf:/openhab/conf \
-v /opt/openhab/userdata:/openhab/userdata \
-v /opt/openhab/addons:/openhab/addons \
-v /opt/openhab/.java:/openhab/.java \
--device=/dev/ttyUSB0 \
--user=<uid> \
openhab/openhab:<arch>
ExecStop=/usr/bin/docker stop -t 2 %n ; /usr/bin/docker rm -f %n
[Install]
WantedBy=multi-user.target
Where <uid>
is the user ID number for the openhab
user which you can obtain using the command id openhab
and <arch>
is the architecture of your system. It is important that ID number is passed in as the ID for the openhab
user inside the container will not match the id of the user on your host system and file permissions may be a bit odd (e.g. why does www-data own my openHAB config files?)
Place this openhab2.service file into /etc/systemd/system
.
Then run sudo systemctl enable openhab2.service
.
Finally run sudo systemctl start openhab2.service
to start openHAB running.
Explanation of Arguments Passed to Docker
-
/usr/bin/docker run
: create a new container from the passed in Image (last argument) -
--name=openhab
: give the container a human remember able name -
--net=host
: by default Docker will place a container into its own network stack. However, openHAB 2 requires UPnP discovery so this parameter makes the Docker container use the hostâs network stack. -
-v /etc/localtime:/etc/localtime:ro
: ties the time of the container to the hostâs time, read only so the container cannot change the hostâs time -
-v /etc/timezone:/etc/timezone:ro
: ties the timezone of the container to the hostâs time zone, read only so the container cannot change the hostâs time zone -
-v /opt/openhab/conf:/openhab/conf
: location of the conf folder for openHAB configurations (NOTE: you must create these folders on the host before running the container) -
-v /opt/openhab/userdata:/openhab/userdata
: location for logs, cache, persistence databases, etc. -
-v /opt/openhab/addons:/openhab/addons
: only needed if installing addons unavailable via PaperUI or the Karaf Console -
-v /opt/openhab/.java:/openhab/.java
: needed by the Nest binding (and others?), location of the security token -
--device=/dev/ttyUSB0
: location of my zwave controller, change and/or add more --device tags to pass all your devices needed by openHAB to the container -
openhab/openhab:amd64-offline
: name of the Docker Image
Updating the Image
Use the following steps to update the docker image and all installed add-ons.
Stop the container:
docker stop openhab
Delete the container:
docker rm openhab
Delete the contents of /opt/openhab/userdata/cache
and /opt/openhab/userdata/tmp
rm -rf /opt/openhab/userdata/cache
rm -rf /opt/openhab/userdata/tmp
Pull down the latest image:
docker pull openhab/openhab:<arch>
where <arch>
is your architecture.
Restart the container using the full command above.
With this upgrade approach it is best if one has configured OH using the cfg files (including addons.cfg) rather than using PaperUI or Habmin.
There is an alternative to deleting the cache and tmp directories.
Karaf Console
- Log into the Karaf console
ssh openhab@localhost -p 8101
- Run
bundle:update <id>
where<id>
is the ID of the addon as listed when you runbundle:list
- Repeat step 2 for all bindings
With this approach you can maintain the installation and configuration of OH in PaperUI or Habmin but must update everything individually.
Limitations and Gotchas
-
The Exec binding is likely not going to be very useful. The container has very little installed (e.g. no Python, ping, hping3, etc.) and almost no access to the hostâs file system which eliminates most of the benefit from this binding. To get around this run an external service on the host that can receive commands from OH via REST or MQTT.
-
The openHAB 2.0 Network binding has limited use. The Docker Image does not have âpingâ installed so the âuse system pingâ option cannot be set to true, and I could not find a way to give the Docker Container permission to bind to low numbered ports so the dhcp option doesnât work.
-
The ssh key used to ssh into the Karaf console changes every time you update the container. Consequently you will have to remove and reaccept the known hosts key from where every you ssh into your console to every time you restart the service.
-
Iâm sure other bindings that require externally installed programs or libraries to work or access to host system information (e.g. systeminfo Binding) will similarly have limited use.