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

时间:2019-03-26 04:35:50

标签: linux docker raspberry-pi docker-compose

我有一个应在树莓派上运行的python应用程序。我创建了一个docker-compose文件进行设置,我的入口点恰好是一个shell脚本,用于检查主机上的各种内容,例如:

  1. 确保SPI已启用(如果未启用),然后通过访问/boot/config.txt并对其进行写入来启用它。
  2. 安装并启用看门狗服务。
  3. 将docker容器写入/etc/rc.local来在重启时自动运行docker容器(尽管我正在考虑将其替换为restart:docker-compose文件中的always或non-stopped标志)

问题是,如果启用SPI,则需要重新启动raspberry pi才能进行设置(不太确定为什么),但是当我的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 个答案:

答案 0 :(得分:2)

我的第一个猜测是,您只需要向容器暴露/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