docker - 如何解决 exceptions.OSError: [Errno 1] Operation not allowed (docker container)?
问题描述
我正在尝试使用bluepy扫描 BLE 设备。我的scan.py代码是——
from bluepy.btle import Scanner, DefaultDelegate
class ScanDelegate(DefaultDelegate):
def __init__(self):
DefaultDelegate.__init__(self)
def handleDiscovery(self, dev, isNewDev, isNewData):
if isNewDev:
print "Discovered device", dev.addr
elif isNewData:
print "Received new data from", dev.addr
# prepare scanner
scanner = Scanner().withDelegate(ScanDelegate())
# scan for 5 seconds
devices = scanner.scan(5.0)
for dev in devices:
print "Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi)
for (adtype, desc, value) in dev.getScanData():
print " %s = %s" % (desc, value)
根据文档(最后作为注释提到)-
(1) LE scanning must be run as root
这意味着我们需要使用sudo
. 我运行它 -
sudo python scan.py
基本上bluepy-helper需要sudo
扫描。需要设置blupe-helper的功能才能在没有sudo
. 根据解决方案,我做了-
sudo setcap 'cap_net_raw,cap_net_admin+eip' /usr/local/lib/python2.7/site-packages/bluepy/bluepy-helper
现在从终端运行扫描代码,无需sudo
像 --
python scan.py
最后,我做了一个 Dockerfile——
FROM arm32v7/python:2.7.15-jessie
WORKDIR /usr/app/gfi_ble
COPY . /usr/app/gfi_ble
RUN chmod 755 ./setcap_for_bluepy_helper.sh
RUN pip install -r requirements.txt
CMD ["./setcap_for_bluepy_helper.sh", "--", "python", "src/scan.py"]
setcap_for_bluepy_helper.sh的内容是——
#!/bin/bash
cmd="$@"
>&2 setcap 'cap_net_raw,cap_net_admin+eip' /usr/local/lib/python2.7/site-packages/bluepy/bluepy-helper
exec $cmd
图像已成功创建,但是当我运行容器时,出现如下错误 -
Creating con_gfi_ble ... done
Attaching to con_gfi_ble
con_gfi_ble | 2019-01-12 23:06:24+0000 [-] Unhandled Error
con_gfi_ble | Traceback (most recent call last):
con_gfi_ble | File "/usr/app/gfi_ble/src/scan.py", line 17, in new_devices
con_gfi_ble | devices = scanner.scan(5.0)
con_gfi_ble | File "/usr/local/lib/python2.7/site-packages/bluepy/btle.py", line 852, in scan
con_gfi_ble | self.start(passive=passive)
con_gfi_ble | File "/usr/local/lib/python2.7/site-packages/bluepy/btle.py", line 789, in start
con_gfi_ble | self._startHelper(iface=self.iface)
con_gfi_ble | File "/usr/local/lib/python2.7/site-packages/bluepy/btle.py", line 284, in _startHelper
con_gfi_ble | preexec_fn = preexec_function)
con_gfi_ble | File "/usr/local/lib/python2.7/subprocess.py", line 394, in __init__
con_gfi_ble | errread, errwrite)
con_gfi_ble | File "/usr/local/lib/python2.7/subprocess.py", line 1047, in _execute_child
con_gfi_ble | raise child_exception
con_gfi_ble | exceptions.OSError: [Errno 1] Operation not permitted
con_gfi_ble |
问题: exceptions.OSError: [Errno 1] Operation not allowed 是什么意思?
当我从终端运行它时,我的代码很好。容器有什么问题?任何想法!
解决方案
Docker 容器以减少的功能运行。这可以防止容器内的 root 通过运行没有命名空间的内核命令以及访问容器外部的主机部分(如原始网络接口或物理设备)来逃避容器。如果需要,您需要在外部向容器添加功能,但请理解这会降低 docker 的默认设置提供的安全性。
从docker run
,这看起来像:
docker run --cap-add=NET_ADMIN --cap-add=NET_RAW ...
https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
在撰写文件中,这看起来像:
version: '2'
services:
app:
image: your_image
cap_add:
- NET_ADMIN
- NET_RAW
参考:https ://docs.docker.com/compose/compose-file/
这不适用于群模式。正在进行工作以增加在集群模式下运行具有附加功能的命令的能力。如果您需要,有一些丑陋的解决方法。
请注意,您不应该sudo
在容器内运行。这样做意味着一切都可以将自己提升为 root 并且违背了以用户身份运行任何东西的目的。相反,您应该以 root 身份启动容器并尽快将其放入普通用户,这是一种单向操作。
推荐阅读
- java - 如何在 Java 中使用 opencv 或 ffmpeg 在网络摄像头流上覆盖视频
- java - 如果我删除不管理此关联的实体,是否有办法让 Hibernate 处理删除 @ManyToMany 关联中的条目?
- lua - 错误 main.lua:98:尝试索引本地“e”(一个数值)
- c++ - Unix TCP socket send() 不能正确下载除 HTML 文件以外的任何其他文件?
- php - 如何从任何控制器 Laravel 5.7 访问模型内的变量?
- hive - 设置什么配置单元属性以避免交叉产品?
- unity3d - 在统一编辑器中,点光源没有亮度
- javascript - 使用 React 和 Node/express 服务器的 SendGrid 配置
- css - 如何在保持可维护性的同时避免移动/桌面 CSS 之间的重复?
- android - Mobilefirst 8 Cordova插件android构建失败