【问题标题】:Connecting to a USB Android device in a Docker container via ADB通过 ADB 连接到 Docker 容器中的 USB Android 设备
【发布时间】:2015-04-10 13:49:14
【问题描述】:

我创建了一个包含 Android SDK 的 Docker 映像,并试图在运行此映像的容器中公开我的 Android 手机。所以我使用--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

主机操作系统

$ 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 的解决方案,请参阅this answer

标签: android docker adb


【解决方案1】:

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

【讨论】:

  • 在使用了一段时间后,我看到 adb 守护进程在主机上自动启动,这阻止了与 Docker 容器的连接。如果你杀死主机中的 adb 守护进程,那么 Docker 容器的 adb 守护进程就能够与手机通信。
【解决方案2】:

在尝试同样的方法时,我遇到了一些与此相关的其他问题,我想分享这些问题,以便其他人可以节省他们的时间:

问题1:容器中没有安装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

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

How to connect ADB devices to Linux container

【讨论】:

  • “我发现这个 URL 非常有用”...来自编写上述 URL 的人,似乎 非常可疑。您应该披露您与博客文章的从属关系。
  • @FrankerZ 我写了这个博客,如果你认为这违反了任何 SO 规范,我可以删除 url
  • 撰写博客并链接到它并不违反 SO 政策。链接到它,而不是透露你是作者,是一个问题。另外,使用大写 i's。
  • 你的 +10 分是命令:adb-kill server 用于避免 docker 的主机阻止来自 cotainer 的 adb。
【解决方案3】:

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

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

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

【讨论】:

  • 您介意解释一下host.docker.internal 的更多细节吗?我尝试docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_id 获取容器的IP 地址,然后尝试adb -H 172.xx.x.x devices,我收到此错误** Cannot start server on remote host error: cannot connect to daemon
  • @Corey ,我遇到了那个错误。就我而言,该错误是由于 adb-server 尚未在主机 (172.xx.x.x) 上运行。 adb 实际上是两个组件,一个客户端和一个服务器,通常运行在同一台主机上,如果服务器没有运行,那么客户端将启动它然后连接到它。因为它们位于不同的服务器上,所以您需要使用“adb start-server”在 docker 主机上手动启动服务器。希望对您有所帮助。
  • 奇怪的是这是第一次工作。 Windows 10 主机,只需确保主机端服务器预先运行。
  • @Corey 我必须在主机 (Windows) 上启动守护程序,就像在主机上运行 adb 设备并稍微等待服务器启动一样简单。如果有帮助,我正在“提升”我的容器运行,否则我昨天安装了 Docker 完全是香草。
  • 这让我的 adb 段错误太奇怪了。我使用 windows 作为主机。
【解决方案4】:

仅使用 --privileged -v /dev/bus/usb:/dev/bus/usb 运行对我不起作用。 我尝试使用 -p 5037:5037 转发 adb 守护程序的侦听端口,但这也无济于事。

只有在我添加了--net host 后它才起作用。 这意味着主机的网络接口会暴露给 docker,所以如果您对此感到满意,请使用它。可能除了5037之外还有更多的端口需要转发......

【讨论】:

  • 只需要 5037。比如ssh -N -L 0.0.0.0:5037:127.0.0.1:5037 $host只需要通过ssh隧道转发adb即可。
【解决方案5】:

更新:

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

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


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

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

主机无法运行adbd,因为在任何给定时间只有一个adbd 可以与电话通话。

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

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


事实上,因为我们在 Linux 上运行,我们可能只需要设置 udev 脚本,每个 Howto run a script when a USB device is pluged in

【讨论】:

    【解决方案6】:

    打扰一下。但我无法回答this 的问题,所以我在这里写下来。

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

    我是如何解决这个问题的:

    我很感兴趣这个问题还会出现在 Docker 容器中吗?答案是“不!”。

    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 文件夹

    【讨论】:

      猜你喜欢
      • 2016-09-21
      • 2020-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多