WiFi-connect installation in Raspberry Pi Docker container

Hi Balena support team!

I’m having a very hard time installing wifi-connect app in my raspberry pi docker container.

I downloaded the wifi-connect source on my pi and built a docker image by using a Dockerfile. Below is a part of Dockerfile related to wifi-connect app installation.
image
But I got the following error while running raspbian-install.sh.
WiFi Connect Raspbian Installer: command failed: systemctl not found

So I installed systemd in my docker container by apt-get install systemd
After that, I run the shell file again, but I also got an error saying that sudo command not found
So I removed all sudo in the script and rerun it. Then I got another error.
WiFi Connect Raspbian Installer: command failed: systemctl -p LoadState --value show NetworkManager

I tried to solve this error, but I didn’t any solution for it.
And I tried other ways to install wifi-connect app in the docker container, but they didn’t work for me.

  • How can I solve the error above?
  • Is there a better solution to install this app in the Raspberry Pi docker container?
  • Is it possible to install this balena app as a docker container? I see some description for using this app as a docker container in README. But is that only possible when using balenaOS? I see a docker image named as wifi-connect in dockerhub. Can I use it using docker-compose file?

Thanks in advance.
Anatoli

If in a container, wifi-connect needs host networking and access to the system’s dbus bus. So you need to run the wifi-connect container in a way similar to this:

$ docker run --network=host -v /run/dbus/:/run/dbus/ wifi-connect

You may need to tweak this command and maybe set the DBUS_SYSTEM_BUS_ADDRESS env var depending on how dbus is set up both inside raspbian and inside the container.

Hi @Ereski
Thanks for your quick reply.

I’ll try this command.

$ docker run --network=host -v /run/dbus/:/run/dbus/ wifi-connect

Could you please let me know how to set DBUS_SYSTEM_BUS_ADDRESS env for my case? I am new to docker setup.

I still have a question. I’d like to know if I can add the following service to my docker-compose.yml to install wifi-connect container.

version: '3'

services:
    wifi-connect:
        build: ./wifi-connect
        network_mode: "host"
        labels:
            io.balena.features.dbus: '1'
        cap_add:
            - NET_ADMIN
        environment:
            DBUS_SYSTEM_BUS_ADDRESS: "unix:path=/host/run/dbus/system_bus_socket"

As you can see, the docker-compose file version I’m using is ‘3’.
I want to run wifi-connect container using docker-compose as much as possible because I don’t want to use manual command like docker run. Can I add the above service to my docker-compose.yml file without any change?

That looks correct however, Balena does not support version 3 docker-compose configurations. Checkout https://github.com/balena-io-examples/balena-multiapp-project for a complete example project using wifi-connect in a docker-compose file. Note this setup uses privileged: true for the wifi-connect but that is not needed since you’re adding the network admin privileges to the container.

Thanks for your reply.
I just tried this.

$ docker run --network=host -v /run/dbus/:/run/dbus/ wifi-connect

But I got the following error.


I have already logged in to dockerhub.com on my raspberry pi.
Can I solve this issue?

Anatoli

When you use docker run it checks the local machine for any image tagged wifi-connect then the registry on docker hub. If no profile is specified for a repository then docker by default adds the library user. So what your command just did is try to find a locally built wifi-connect image but didn’t so it then looked in the registry for an image tagged library/wifi-connect which does not exist.

The wifi-connect repository is just the project source code itself. There are no published images. If you want to run a built image of wifi-connect then you want to use one of the images from: https://hub.docker.com/r/balenablocks/wifi-connect/tags?page=1&ordering=last_updated. Those images are published from https://github.com/balenablocks/wifi-connect which is apart of our work to help make these balena projects easier to deploy.

We have a blog post that also explains what we’re trying to do with balengaBlocks https://www.balena.io/blog/introducing-balenablocks-jumpstart-your-iot-app-development/.

If you’re running balenaOS I would highly advise against managing containers yourself and rather just add them to your release. If this is not the case then make sure to include --cap-add=NET_ADMIN to the docker run you shared.

Hi @20k-ultra
How are you?

I have tried two ways to install wifi-connnect on my raspberry pi4.
However, they didn’t work for me. I’m using Raspbian OS, not balenaOS.
Here are the test results.

  1. Using docker run command

    pi@raspberrypi:~/DTECTS_SW_Server_Side $ docker run balenablocks/wifi-connect:rpi --network=host --cap-add=NET_ADMIN -v /run/dbus/:/run/dbus/ wifi-connect
    Unable to find image 'balenablocks/wifi-connect:rpi' locally
    rpi: Pulling from balenablocks/wifi-connect
    9ff317847eda: Pull complete
    c5136835926a: Pull complete
    e05a6a4895e4: Pull complete
    d63dc2e2e6de: Pull complete
    Digest: sha256:ddb264075f5cc9d62cfbd16563ea6d34fea912c27dcf71709c1c3085370787e6
    Status: Downloaded newer image for balenablocks/wifi-connect:rpi
    docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "--network=host": executable file not found in $PATH: unknown.
    ERRO[0012] error waiting for container: context canceled
    
  2. Adding a service for wifi-connect to docker-compose.yml
    I have added a service for wifi-connect to my docker-compose.yml file and built a new docker image.


    When I checked the status of the containers, it looks like the container for wifi-connector is running.

    pi@raspberrypi:~/DTECTS_SW_Server_Side $ docker ps
    CONTAINER ID   IMAGE                           COMMAND                  CREATED          STATUS          PORTS                    NAMES
    b681d4c6a41e   dtects_sw_server_side_django    "bash docker-entrypo…"   58 minutes ago   Up 58 minutes   0.0.0.0:8000->8000/tcp   dtects_sw_server_side_django_1
    0b7343312cca   grafana/grafana:latest          "/run.sh"                58 minutes ago   Up 58 minutes   0.0.0.0:3000->3000/tcp   dtects_sw_server_side_grafana_1
    4e355d1d906c   jsurf/rpi-mariadb               "docker-entrypoint.s…"   58 minutes ago   Up 58 minutes   0.0.0.0:3306->3306/tcp   dtects_sw_server_side_db_1
    de7a1ce7973b   balenablocks/wifi-connect:rpi   "/bin/busybox sh sta…"   58 minutes ago   Up 58 minutes                            dtects_sw_server_side_wifi-connect_1
    

    Does that mean the wifi-connect app is currently running? Or does it just mean that this app is installed inside the container? I didn’t see WiFi Connect access point on my phone.
    I tried to access to the container by docker exec -it containerID /bin/bash command, but I also got the same error as in the first method.

    pi@raspberrypi:~/DTECTS_SW_Server_Side $ docker ps
    CONTAINER ID   IMAGE                           COMMAND                  CREATED              STATUS              PORTS                    NAMES
    b681d4c6a41e   dtects_sw_server_side_django    "bash docker-entrypo…"   About a minute ago   Up About a minute   0.0.0.0:8000->8000/tcp   dtects_sw_server_side_django_1
    0b7343312cca   grafana/grafana:latest          "/run.sh"                About a minute ago   Up About a minute   0.0.0.0:3000->3000/tcp   dtects_sw_server_side_grafana_1
    4e355d1d906c   jsurf/rpi-mariadb               "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:3306->3306/tcp   dtects_sw_server_side_db_1
    de7a1ce7973b   balenablocks/wifi-connect:rpi   "/bin/busybox sh sta…"   About a minute ago   Up About a minute                            dtects_sw_server_side_wifi-connect_1
    pi@raspberrypi:~/DTECTS_SW_Server_Side $ docker exec -it de7a1ce7973b /bin/bash
    OCI runtime exec failed: exec failed: container_linux.go:370: starting container process caused: exec: "/bin/bash": stat /bin/bash: no such file or directory: unknown
    

The basic reason I want to run this app in Docker is that I need to run it using the sudo wifi-connect command in a web container that works on the same Docker image. The wifi-connect app is working well outside the docker image. But I need to run this app in the docker container.

I am really struggling with this! How can I achieve this purpose? How can I solve the above issues?
I really want you come up with a good solution.

Anatoli.

Hi @20k-ultra

How are you? I’m still waiting for your reply.
As you recommended two days ago, I have followed the following git repository to make wifi-connect container.


I made two changes in docker-compose.yml and Dockerfile.template before building the image.
  1. I disabled all other services from docker-compose.yml except for wifi-connect service.

  2. I replaced FROM balenalib/%%BALENA_MACHINE_NAME%%-debian with the following line in Dockerfile.template.

    FROM balenalib/raspberrypi3-debian:latest
    

    The reason I made this change is that I got the following error on the first line when building the docker image using the default Dockerfile.

    Step 1/6 : FROM balenalib/%%RESIN_MACHINE_NAME%%-debian
    ERROR: Service 'wifi-connect' failed to build : invalid reference format: repository name must be lowercase
    
  3. Renamed Dockerfile.template as Dockerfile.

After making the above three changes, I run docker-compose up -d --build, but I got the following error in the step 4.

I am using pi 4 and have installed the latest version of raspbianOS. Is it really impossible to have a wifi-connect container running on RaspbianOS? Or did I make a mistake anywhere?
Otherwise, the wifi-connect app can run as docker container only on balenaOS?

Anatoli

You need to replace the %%RESIN_ARCH%% template variable with the correct architecture you need, because it is specific to Balena and Dockerfile.template, and not a regular Dockerfile. So this will be either armv7hf or aarch64 depending on whether you run a 32-bit or 64-bit Raspbian.

Hi @majorz

Thanks for your help. I built the docker image and run it without any issue as you told me, but I still have some questions.

  1. How to run wifi-connect in the docker container?
    I see the wifi-connect container is working by docker ps command. Does it mean that the wifi-connect is running? If so, I’ll have to see the raspberry pi that works as an AP, but I didn’t see it.
    As you know, when I installed wifi-connect outside the docker, I have to type sudo wifi-connect command to run it. Inside the container, how can I run this app?

  2. Is it possible to run wifi connect on the different web container?
    The ultimate goal was to run this app on the different web container when needed.
    The web container service and wifi connect container service have been defined in the same docker-compose.yml file. The web container has a function that runs sudo wifi-connect command when clicking a button on web page. So I’d like to know if I can call wifi-connect installed on its container from another container.
    I hope you understand my idea.

  3. Is it possible to install and run wifi-connect inside the web container?
    I want to use wifi connect app inside the web docker container running on my raspberry. In that case, I can call it anytime in the web container.
    I download the wifi-connect git repository on the web container and executed raspbian-install.sh file like installing it in Raspberry Pi without using dokcer, but I got some errors. I already solved some problems, but I can’t fix the following error.

I’m very struggling with this problem for a few days. Please help me!

Thanks
Anatoli

raspbian-install.sh is supposed to be run on raspbian, not in a container.
It disables dhcpcd and installs NetworkManager and wifi-connect.
NetworkManager must be running on the host OS, not in the container.

You’ll need to:

Hi Alexis,

I’m a little confused.
Those steps are for installing and starting wifi-connect in the web container? Or those steps are for building and starting a container for wifi-connect only?
I just need to install and run wifi-connect in the web container.

In the step4, it’s to build and run a container for wifi-connect. Right?
Or should I run all commands inside the web container?

Or

Hi. What do you mean by web container? Could you explain in more detail in what environment you want to use wifi-connect?

Sorry to confuse you! I’ll explain my work in detail.

Here is my docker-compose.yml file.

As you can see, there are two services. One of them is for a web container(django).
This web docker image is built based on Dokcerfile-dev.
I have already run two containers using docker-compose up -d --build command. They’re working well.
I want to install and run wifi-connect inside the web container(django). In order to do that, I added a volume and environment to docker-compose.yml file as follows.

- /var/run/dbus/system_bus_socket:/host/var/run/dbus/system_bus_socket
- DBUS_SYSTEM_BUS_ADDRESS="unix:path=/host/run/dbus/system_bus_socket"

And I added RUN apt-get install -y systemd and RUN apt-get install -y dbus to Dockerfile for the web container because systemd and dbus are needed to install wifi-connect.
Here is Dockerfile for the web container.

FROM python:3.7.3
ENV PYTHONUNBUFFERED=0
WORKDIR /app
ADD requirements.txt /app/
RUN pip3 install -r requirements.txt
RUN pip3 install netifaces

RUN apt-get install -y systemd
RUN apt-get install -y dbus
RUN apt-get install -y supervisor
RUN service supervisor restart

COPY . /app
ADD uart.conf /etc/supervisor/conf.d
ADD net_monitor.conf /etc/supervisor/conf.d

WORKDIR /app/wifi-connect/scripts
RUN chmod +x raspbian-install.sh

WORKDIR /app
RUN chmod 774 docker-entrypoint.sh
ENTRYPOINT ["bash", "docker-entrypoint.sh"]

As you can see, the web container includes balena-io/wifi-connect git source.
After building the docker image using docker-compose up -d --build command, two containers are working well.
I went into the django container and tried to install and run wifi-connect.
The problem is from now on.
When I run raspbian-installer.sh file in django container, I got the following error.

pi@raspberrypi:~/DTECTS_SW_Server_Side $ docker exec -it d8426c7fa4c8 /bin/bash
root@d8426c7fa4c8:/app# bash wifi-connect/scripts/raspbian-install.sh
WiFi Connect Raspbian Installer: Retrieving latest release from https://api.github.com/repos/balena-io/wifi-connect/releases/latest...
WiFi Connect Raspbian Installer: Downloading and extracting https://github.com/balena-io/wifi-connect/releases/download/v4.4.4/wifi-connect-v4.4.4-linux-rpi.tar.gz...
WiFi Connect Raspbian Installer: Successfully installed wifi-connect 4.4.4
Failed to connect to bus: Connection refused
WiFi Connect Raspbian Installer: command failed: systemctl -p LoadState --value show NetworkManager

I have already installed wifi-connect on hostOS (raspbian). I think it means that NetworkManager has been already installed. And as I mentioned above, I mounted dbus in host OS to dbus in the container.
But I still have the same error.
I hope the above explanation helps you understand my problems
How can I solve this problem?
If you are not sure, please let me know.

Anatoli

Hi Anatoli,

Is there a reason you want to run wifi-connect in the same container as your Django app?

My understanding of the project is that the raspbian-install.sh script is meant to automate installing wifi-connect on Raspbian outside of a container. You might encounter issues with using it inside a container, especially one running another app.

What might work better is running wifi-connect as a separate service. See balena-dash as an example. https://github.com/balenalabs/balena-dash

Hi Joseph,

The basic reason I want to install and run wifi-connect in the web container is to run wifi-connector when the user clicks a button on a web page. The djagon backend running on the web container should execute sudo wifi-connect command when the user clicks AP mode button on the web page. In order to do that, wifi-connect should be installed in the web container.
Does it make sense?
If the we have a specific container only for wifi-connect, is there any way to call wifi-connect from the web container?
I am really struggling with this for a few days! How can I achieve this purpose?
I really want you come up with a good solution.

Hi Anatoli,

You can run wifi-connect from within your python container. You’d need to install the latest version of wifi-connect in your container to have access to it.

You can refer to this playground project for reference on how to do that: https://github.com/balena-io-playground/balena-wifi-connect-example

Note: The reference project is a bit old and you might have to replace resin with balena at places.

Hi Amit,
Happy new year! Thanks for your help.

As you told, this repository is old. So I needed to make some changes on Dockerfile and start.sh file.
First of all, I disabled all other features except for wifi-connect in Dockerfile.
And I replaced resin with balena. You can see the modified Dockerfile and start.sh below.

In order to run the container, I had to add some options to docker run as follows.

docker run --mount type=bind,source=/run/dbus/system_bus_socket,target=/host/run/dbus/system_bus_socket -e DBUS_SYSTEM_BUS_ADDRESS="unix:path=/host/run/dbus/system_bus_socket" test:1.0

Here test:1.0 is a tag attached to the image I built using the above Dockerfile.
When I run docker container with above command, I see the follow error.

pi@raspberrypi:~/balena-wifi-connect-example $ docker run --mount type=bind,source=/run/dbus/system_bus_socket,target=/host/run/dbus/system_bus_socket -e DBUS_SYSTEM_BUS_ADDRESS="unix:path=/host/run/dbus/system_bus_socket" test:1.0
Deleting already created by WiFi Connect access point connection profile: "WiFi Connect"
WiFi device: wlan0
Access points: ["Almond3d21"]
Starting access point...
Access point 'WiFi Connect' created
Starting HTTP server on 192.168.42.1:80
Error: Cannot start HTTP server on '192.168.42.1:80': address not available

As you can see, an error occurs in the process of starting the AP server on 192.168.42.1.180.
Your solution seems to be most effective solution I’ve ever tried.
Is there any way to resolve the above error?
In the modified Dockerfile I see ENV DEVICE_TYPE=%%RESIN_MACHINE_NAME%%.
Should I replace %%RESIN_MACHINE_NAME%% with raspberry pi4? (I’m using Raspberry PI4)

I hope you get back to you with the best solution.

Thanks
Anatoli

Error: Cannot start HTTP server on ‘192.168.42.1:80’: address not available

wifi-connect needs to start a web server on port 80.
This port is already being used (most probably by your web application).
Thus wifi-connect can not start.

You can change the port used by wifi-connect, see https://github.com/balena-io/wifi-connect/blob/master/docs/command-line-arguments.md