Home

Running a full desktop in a container

While building your next Internet-of-things (IoT) project, sometimes you get to a point where you need to run applications that are made to run on a screen, we call them graphical user interface (GUI) applications.

After multiple requests from our users, we decided to write a short tutorial explaining how you can run a desktop manager or a GUI application with balenaCloud or openBalena on any kind of display.

To get started, you will need an account for balenaCloud. If you are new to the balena ecosystem, take a look at the introduction first, as the initial setup of your account and provisioning a device is outside the scope of this guide.

This tutorial will set you up with an example project that runs a desktop manager so that you’re able to run GUI applications and display them on an LCD screen. The project is also designed to work on multiple devices such as a Raspberry Pi or an Intel NUC.

Downloading the application

To get started, go to the GitHub repository and clone or download the project into your computer.

Click on Clone or download then on the Download ZIP button to get the files you will need. If you are already familiar with Git you can use git clone in the same way you would usually do.

Pushing the code to the device

Let's first push the project code to the device without any changes to make sure everything works. Once you have the files on your computer, using the terminal, go to the directory you cloned or unzipped the files into and push the code to the device already connected to balenaCloud.

For this, we will use the balena cli tool, where you can push the code by running balena push <ApplicationName> in the same folder as the project. You can read more about the CLI here.

If everything worked OK, you'll see the magic unicorn 🦄:

Good job, things are looking promising!

In this project, we are demonstrating the use of a new feature of balenaCloud that allows you to target different device types and architectures with separate dockerfiles. If you check the project root folder, you will notice that there are two dockerfiles, Dockerfile.raspberrypi3 and Dockerfile.template.

If you are running this project on a Raspberry Pi 3, the docker container will be created based on the Dockerfile.raspberrypi3, which will install RASPBIAN and use the PIXEL Desktop Manager. For all other devices, it will install and use XFCE Desktop Manager.

Multiple docker files

The multiple docker file feature works by scanning the folder for dockerfiles and matching the correct one with your application device type. For example, if you want to run a similar code base on two different device types, you could have one application configured for the Raspberry Pi 3 and another for the BeagleBone Black. By having two dockerfiles, Dockerfile.raspberrypi3 and Dockerfile.beaglebone-black, when building the docker image, the system will choose the right configuration for each device. 🧙

In order to target a specific device type or architecture, the extension for the Dockerfile must match BALENA_MACHINE_NAME for device-type and BALENA_ARCH for architecture. A list of the available values for each of these variables is available at https://www.balena.io/docs/reference/base-images/devicetypes/.

The files are processed in the following order of preference:

  • Dockerfile.<device-type>
  • Dockerfile.<architecture>
  • Dockerfile.template

After pushing the project to balenaCloud, it will download onto your device and if everything works as planned, you’ll be able to see the desktop manager on the screen, just like the Raspberry Pi example in the image below:

If you’re using an X86 device such as the Intel NUC, the project will deploy XFCE and look something like the below:

This project supports the use of a keyboard and mouse directly connected to the deployed devices in order to provide input to the GUI.

You now have a plain version of either the Raspbian Desktop or XFCE running on your device, it’s time to learn how to add new applications to it and also configure them to start automatically on boot!

Adding extra applications to the docker file

The base project comes with just the bare minimum required to run the desktop manager. In order to add applications to your setup, you need to change the dockerfile so that they can be installed during the image build.

The easiest way to install applications to your project is by using apt-get, where based on the docs, you can use the command install_packages as a shortcut, which additionally handles the clean up of any temporary installation files afterward. In this example, you can add an extra \ at the end of matchbox-keyboard and add all the applications you need on the line underneath.

For example, if you want to run a terminal emulator such as xterm the install_packages part of the dockerfile will be:

RUN install_packages xserver-xorg \  
    xinit \
    lxsession \
    desktop-file-utils \
    raspberrypi-ui-mods \
    rpd-icons \
    gtk2-engines-clearlookspix \
    matchbox-keyboard \
    xterm

If you have any questions on this (or any other) step, please start a thread on our forums where our team will be happy to help.

Running an application on boot

Depending on your project, you may want to start an application as soon as the desktop manager starts. Due to the differing window managers, the process to do this is slightly different depending on what device you’re using.

Raspberry Pi

The first thing to do is edit Dockerfile.template and uncomment the line COPY autostart /etc/xdg/lxsession/LXDE-pi/autostart.

Next, edit the file autostart. On the last line change xterm to your desired application.

Below you can see the results of the example above where we start the xterm application automatically when the device boots.

Other devices (e.g. X86 Intel NUC)

In other devices, to run an application on startup, you can edit the file start_x86.sh and change the startx to add the application you want to autostart, for example, startx xterm.

Rotating the screen

In case you need to rotate the screen, all you need to do is to open balenaCloud dashboard and add or edit environment variables.

Raspberry Pi

When working with a Raspberry Pi, the configuration will vary if you are using a display connected via HDMI or via the LCD DSI Display Connector.

HDMI: To configure the Raspberry Pi to use the HDMI connector, click on Device Configuration and at the bottom where it says CUSTOM CONFIGURATION VARIABLES, add new custom variables:

  • BALENA_HOST_CONFIG_hdmi_boost=9
  • BALENA_HOST_CONFIG_hdmi_force_hotplug=1
  • BALENA_HOST_CONFIG_hdmi_group=1

Now to rotate the display, you can use the variable called BALENA_HOST_CONFIG_display_rotate with a value from 0 to 3 with (0, 90, 180 and 270 degrees).

LCD DSI Display Connector: In case your display is attached to the DSI connector, you can add the custom variable BALENA_HOST_CONFIG_lcd_rotate with a value from 0 to 3 which corresponds to 0, 90, 180 and 270 degrees.

Other devices

Similar to the configuration above, go to Device Variables and add a new variable called ROTATE_DISPLAY with the values of normal, right, inverted, or left which corresponds to 0, 90 180 and 270 degrees.

Conclusion

In this post, you saw how you can easily start a project that requires a desktop manager with balenaCloud. Now it’s up to you to create an amazing project with it!

Thanks for reading! If you followed this tutorial we’d love to hear how it went, similarly, if you got stuck or have any questions, let us know in our forums at https://forums.balena.io, on Twitter @balena_io, on Instagram @balena_io or on Facebook. See you next time! ;)

comments powered by Disqus