Docker Not Exporting Display On Startup

Hi there,

I have built a GUI application with Tkinter and Python3 and I am trying to display it on a VNC screen. I have followed Balena’s tutorial on VNC application with balena and it works fine. However, I want to export the screen on start up. Everytime I push code to my device, I have to manually execute this code

export DISPLAY=:1

I have tried doing things with the Dockerfile.template, start.sh, and even the supervisor config files but none of these work and I have to continue doing this manually. Is there anyway to resolve this?

Hi

Looks like you are trying to set an environment variable. You can do so using environment and service variables - see our docs here.

Let us know if that works for you

Is there any reason why this would not work (specifically the export DISPLAY part)?

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && export DISPLAY=:1

It is in my dockerfile.template file.

Hey Nathaneal

The RUN command you have put above is for the dockerfile itself, and so will run on the builder. This command won’t be run on the device itself. To do what you need, you will need to put your command(s) into a bash shell script file, and make the dockerfile run that using the CMD command. There are more details to this here:
https://www.balena.io/docs/learn/more/masterclasses/docker-masterclass/#44-cmd-directive

Let me know how you get on!
Phil

I have tried the CMD function in both start.sh and a separate .sh file but none of these seem to work. I have tried executing an echo "STARTING EXPORT DISPLAY" but that doesn’t seem to execute either. The other commands in these sh files seem to work though. Am I doing something wrong?

Hi Nathaneal

Did you manage to take a look at our masterclass linked above? It gives you some good examples of running the CMD directive. This is a docker command so doesn’t run in the bash script, but makes a bash script run on the device itself. If you put your shell commands inside your start.sh and run this file with the CMD directive, you should see the result of your echo in the service logs within balenaCloud. Can you confirm whether you can get that part to work?

Phil

I have this at the end of my Dockerfile.template:

CMD ["bash", "start.sh"]

And in my start.sh I have the following at the end:
echo "SETTING OUTPUT DISPLAY TO VNC"
export DISPLAY=:1

But it does not work unfortunately.

Hey - when you say it does not work, do you get the echo output in your device logging in balenaCloud?

Could you send me the contents of your dockerfile in full, and if you are using a docker-compose file send that as well? Just to check nothing is amiss in those.

Also, I’ve just found a relevant example in our Github, which you can follow:

Maybe that helps you out more?

Phil

Update: So having a separate file didn’t do anything either - I don’t know if it executed but the echo did seem to work but the file still failed to open.

Here’s my Dockerfile.template:

FROM balenalib/%%BALENA_MACHINE_NAME%%-debian:buster

RUN install_packages x11vnc \
    x11-utils \
    xvfb \
    wmctrl \
    supervisor \
    python3 \
    python3-pip \
    python3-tk \
    python3-setuptools \
    libatlas-base-dev \
    python3-cffi \
    libcairo2 \
    libpango-1.0-0 \
    libpangocairo-1.0-0 \
    libgdk-pixbuf2.0-0 \
    libffi-dev \
    shared-mime-info \
    python3-gi \
    python3-gi-cairo \
    gir1.2-gtk-3.0 \
    python3-cairo \
    python3-matplotlib

ADD /growatt_api_client /growatt_api_client

WORKDIR /app

ADD requirements.txt /app

RUN pip3 install -r requirements.txt

WORKDIR /usr/src/app

COPY . .

ADD supervisor /etc/supervisor

ENV TZ=Australia/Adelaide

RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

CMD ["bash", "start.sh"]

And here’s my start.sh:

#!/bin/bash

echo "${TZ}" > /etc/timezone
dpkg-reconfigure tzdata

if [ -z ${VNC_PASS} ]; then
  echo "STARTING VNC WITHOUT PASSWORD"
  supervisord -c /etc/supervisor/supervisord_np.conf  
else
  echo "STARTING VNC WITH PASSWORD"
  supervisord -c /etc/supervisor/supervisord.conf
fi

echo "SETTING OUTPUT DISPLAY TO VNC"
export DISPLAY=:1 

Hi - I think it is worth you spending the time going through our Docker Masterclass (linked above) and making sure you understand what each of the commands is doing, and where they are run (i.e. in the builder or in the container). Also, try running the timezone example linked above, and make sure you understand how that example is running. That will give you a good basis for getting your solution to work. Also, we have an example which exports the display, which you can also see how we do it ourselves:


specifically in this file:

Hope that helps,
Phil

Thank you for the resources Phil. I might switch to using balena-dash as it might be more catered for my needs.

I looked at the start.sh you linked above and I tried to do some things. However, when going through start.sh, it seems to execute that function but the variable is not translated for some reason.

#!/bin/bash

echo "SETTING OUTPUT DISPLAY TO VNC"
export DISPLAY=:1
echo $DISPLAY

echo "${TZ}" > /etc/timezone
dpkg-reconfigure tzdata

The echo's do work and in balena console I see SETTING OUTPUT DISPLAY TO VNC as well as :1 for the second echo.

But, when the service starts up, the variable is not translated, as seen in this screenshot:

image

I have to manually export the variable again even though it seems that it is executed on startup. Is there something wrong?

Hi, when you set export Display=:1 it only works for current shell. When you open terminal on dashboard, that’s another instance, that’s why you don’t see previously exported value there (see this answer for explanation).

You can set env var with default value in Dockerfile this way:

ENV Display=:1

I believe I should try the .bashrc way however I cannot find the file in the vnc-app service. Do I have to create it?

Hey,

The easier route would be to create an environment variable either through Dockerfile or through our Dashboard. This way the environment variable will be always available in the container.

Best,
Odysseas

I tried that with karaxuna’s suggestion but my service still did not start up.

I see in your Dockerfile that you already set an env variable ENV TZ=Australia/Adelaide. Can you verify that you can detect that environment variable when you SSH into the container, by running echo $TZ.

Indeed.

image

Hey, the variables that you export from your startup script will not be exported to a shell that you open in the container. Your $TZ variable is set because you use an ENV directive in the Dockerfile, and if you use an ENV directive for DISPLAY, it will be set in the container. If you app still doesn’t work after that, I’m fairly sure the env var is not the problem.

I just checked echo $DISPLAY and it seems that :1 is indeed there. But x11vnc keeps exiting so I might just move on to balena dash or Grafana. Thank you for all the support and sorry for any inconvenience.