通过 ADB 连接到 Docker 容器中的 USB Android 设备

Connecting to a USB Android device in a Docker container via ADB

我创建了一个包含 Android SDK 的 Docker 图像,我正试图在容器 运行 中公开我的 Android phone图片。所以我使用 --privileged 标志并按如下方式安装 USB 设备:

$ docker run --privileged -v /dev/bus/usb:/dev/bus/usb -d -P my-android:0.0.1

但是,当我 运行 ADB 设备时,它没有显示 USB 设备:

ubuntu@d56b666be455:~/Android/Sdk/platform-tools$ ./adb devices
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
List of devices attached

ubuntu@d56b666be455:~/Android/Sdk/platform-tools$

容器内的 lsusb 列出设备:

ubuntu@d56b666be455:~$ lsusb
...
Bus 002 Device 017: ID 04e8:6866 Samsung Electronics Co., Ltd GT-I9300 Phone [Galaxy S III] (debugging mode)

但该设备在主机上可见:

⇒  ./adb devices
List of devices attached
4d11abcd65b74045    device

主持人OS

$ uname -a
Linux ananya 3.16.0-33-generic #44~14.04.1-Ubuntu SMP Fri Mar 13 10:33:29 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

Docker版本

$ docker --version
Docker version 1.5.0, build a8a31ef

可能是什么问题?

我不认为设备上的 ADB 守护程序 运行 可以连接到两个 ADB 服务器。尝试断开它与主机 ADB 的连接,然后将其连接到 Docker 容器的 ADB。

更新:

我最终使用 --privileged 和 -v 来映射整个 /dev/bus/usb 并修补 adb 以接受一个环境变量来指定根 USB 设备树 - /dev/bus/usb/001

这允许我们为相同 phone 的不同组的不同容器使用不同的 USB 总线,另一个环境变量补丁允许不同的 VID:PID 列表用于不同类型的 phone .


我们正在尝试将不同的 USB 总线分配给不同的 Docker 容器 运行ning TeamCity 客户端。

每个容器需要 ANDROID_ADB_SERVER_PORT 设置到不同的端口(因为我们没有使用隔离网络)。

主机不能 运行 adbd,因为在任何给定时间只有一个 adbd 可以与 phone 对话。

每个容器都有 /dev/bus/usb/xxx 目录之一,因此我们可以将 phone 插入特定容器。

我们必须每隔几秒同步一次 /dev/bus/usb/xxx 目录,以允许热插拔和重新启动 - 只是主机上的一个 shell 循环 运行s tar cf devxxx.tar /dev/bus/usb/xxx, docker cp 进行传输,然后 docker exec 在容器 /tmp 内解压,diff 检测要删除的节点,然后 mv -n 将新节点移入。


事实上,因为我们 运行 正在 Linux,我们可能只设置 udev 脚本,根据 Howto run a script when a USB device is pluged in .

虽然我也在尝试同样的事情,但我 运行 遇到了一些与此相关的其他问题,我想分享这些问题,以便其他人可以节省他们的时间:

问题一:容器中没有安装lsusb

在我的例子中 lsusb 没有安装,所以我用下面的命令安装它:

apt-get update
apt-get install usbutils

问题2:安装lsusb和ADB SDK后还是看不到设备

您需要使用 -v 选项重新启动您的容器,是的,不要忘记按照其中一个答案所述终止 ADB 服务器。

在主机上:

adb-kill server
docker run -ti -d --privileged -v /dev/bus/usb:/dev/bus/usb   container_name

如果有人想从头开始,我已经写了一篇博客post:

How to connect ADB devices to Linux container

这并没有回答您提出的确切问题,但确实解决了您试图完成的问题 - 从 adb 客户端连接到连接到 docker 主机的 android 设备 运行 在 docker 容器中。我为任何试图完成同样事情的人(就像我一样)包括这个。

adb 客户端支持 -H 选项,告诉它在哪里可以找到要连接的 adb 服务器。 Docker 支持主机名 "host.docker.internal",它始终映射到 docker 主机的 IP 地址。假设您的设备连接到 docker 主机,您可以执行以下操作让容器化的 adb 客户端连接到 docker 主机上的 adb 服务器 运行:

adb -H host.docker.internal devices

无需安装 USB 端口即可实现目标。

参考:https://developer.android.com/studio/command-line/adb

更新: 我最近了解到,在 18.0 及更高版本中,host.docker.internal 仅在 Docker for Mac 上受支持。

不好意思打扰了。但是我无法回答 this 问题所以我把它写在这里。

我正在使用 ubuntu:18.04 并尝试连接我的 Samsung Galaxy A3 2016 并使用 ADB 对其进行调试。设备未经授权,屏幕上没有弹出对话框!

我是如何解决问题的:

我很感兴趣问题是否仍然会在 Docker 容器中发生?答案是 "No!"。

  1. 在一个 Docker 容器中,我调用了以下内容:(这是本主题的答案:))

    docker run --name android-adb -it -d --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu:16.04 bash
    
  2. 我下载了 platform-tools(使用 ADB 分发)。将其路径添加到环境中。并重新启动 bash

  3. 在 Docker 容器内重新启动 ADB 服务器并终止主机上的 ADB 服务器后。我发现智能手机屏幕上出现了确认对话框!

所以我认为在主机上问题出在 .android 目录中。只需将其移动到 .android-backup。下一个 adb start-server 命令将创建一个新的。我还用最近的

替换了 platform-tools 文件夹

运行 只是 --privileged -v /dev/bus/usb:/dev/bus/usb 对我不起作用。 我尝试使用 -p 5037:5037 转发 adb 守护程序的监听端口,但这也没有帮助。

只有在我添加 --net host 后它才有效。 这意味着主机的网络接口暴露给 docker,所以如果你不介意的话就使用它。也许除了5037之外还有更多端口需要转发....

这对我有用。

  • 将您的设备设置为 PPT 模式
  • (可选)检查设备是否在本地可用 $ adb devices

I try with many options and only one works. Using --network flag as the next example

  • 运行 容器

$ docker run -it --net host ubuntu bash

输出:

List of devices attached
464e128 device

我使用了 this Dockerfile。适用于 flutter 项目