Docker - 从Docker容器内重启树莓派主机

3
我有一个Python应用程序,旨在在树莓派上运行。我已经创建了一个docker-compose文件来设置它,我的入口点恰好是一个shell脚本,它检查主机上的各种事情,例如:
  1. 确保启用SPI,如果没有启用,则通过访问/boot/config.txt并编写它来启用。
  2. 安装和启用看门狗服务。
  3. 通过将其写入/etc/rc.local来自动重新启动我的docker容器(尽管我正在考虑使用docker-compose文件中的restart: always或unless-stopped标志替换它)
问题是,如果我启用SPI,树莓派需要重新启动才能设置它(不太清楚为什么),但当我的shell脚本从docker容器内部达到sudo reboot命令时,我会收到以下错误:
 Failed to connect to bus: No such file or directory
 Failed to talk to init daemon.

我理解它可能正在尝试在Docker容器内查找DBus和init守护程序,但它们不存在。我该如何让我的容器访问这些资源?我需要挂载另一个卷吗?以下是我的docker-compose.yml文件:

version: "3"

services:
    mongoDB:
        restart: unless-stopped
        volumes:
            - "/data/db:/data/db"
        ports:
            - "27017:27017"
            - "28017:28017"
        image: "andresvidal/rpi3-mongodb3:latest"
    mosquitto:
        restart: unless-stopped
        ports:
            - "1883:1883"
        image: "mjenz/rpi-mosquitto"
    FG:
        privileged: true
        network_mode: "host"
        depends_on:
            - "mosquitto"
            - "mongoDB"
        volumes:
            - "/home/pi:/home/pi"
            - "/boot:/boot"
        #image: "arkfreestyle/fg:v1.8"
        image: "test:latest"
        entrypoint: /app/docker-entrypoint.sh
        restart: unless-stopped

FG是我的Python应用程序,入口点是docker-entrypoint.sh,它看起来像这样:

#!/bin/sh
if [ ! -f /home/pi/.initialized ]; then                                                                                                                                                                                    
    echo "Initializing..."                                                                                                                                                                                

    # Turn spi on
    if grep -Fxq "dtparam=spi=on
dtparam=watchdog=on" /boot/config.txt
    then
        echo "\nSPI is already enabled"
        echo "Creating .initialized"
        # Create .initialized hidden file
        touch /home/pi/.initialized
        echo "Starting application..."
        sudo python3 __main__.py -debug
    else
        ### Enable SPI ###
    fi
    fi

    ### Create .initialized file ### 
    echo "Rebooting in ten seconds..."
    sleep 10
    sudo reboot # This line results in the error

else
    echo "Initialized already!"
    sudo python3 __main__.py -debug                                                                                                                                                                                     
fi       

特权选项已经让我的容器可以访问GPIO,我本以为它也可以让我重启,但是似乎不是这样的。请告诉我需要做什么才能重新启动。

1个回答

6

我的第一次猜测是您只需要将/run/dbus/run/systemd暴露给您的容器,像这样:

docker run -v /run/dbus:/run/dbus -v /run/systemd:/run/systemd ...

但仅有这两个绑定挂载是不够的; 只有这样,试图从容器内部与宿主机上的systemd交互会导致:

[root@631fff40f09c /]# reboot
Failed to connect to bus: No data available
Failed to talk to init daemon.

原来这需要容器在主机的全局PID命名空间中运行才能正常工作,因此我们需要:

docker run -v /run/dbus:/run/dbus -v /run/systemd:/run/systemd --pid=host ...

有了这个功能,容器内运行reboot命令可以成功重启主机。

docker-compose.yml中,可以这样写:

FG:
    privileged: true
    network_mode: "host"
    pid: "host"
    depends_on:
        - "mosquitto"
        - "mongoDB"
    volumes:
        - "/home/pi:/home/pi"
        - "/boot:/boot"
        - "/run/dbus:/run/dbus"
        - "/run/systemd:/run/systemd"
    image: "test:latest"
    entrypoint: /app/docker-entrypoint.sh
    restart: unless-stopped

嘿,非常感谢你的帮助!事实证明,只需挂载/run/dbus就足够了,我的容器成功地重新启动了主机 :) 我很好奇为什么没有使用主机的pid也能工作,可能是--net=host或--privileged覆盖了吗? - AbdurRehman Khan
1
不确定。我无法在不使用--pid=host的情况下使其工作。很高兴对你来说结果变得更简单了! - larsks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接