Подключение к USB-устройству Android в контейнере Docker через ADB

Я создал образ Docker, содержащий Android SDK, и пытаюсь выставить свой телефон Android в контейнере с этим образом. Поэтому я использовал флаг --privileged и --privileged USB-устройства следующим образом:

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

Однако, когда я запускаю устройства ADB, он не показывает мне устройство USB:

[email protected]:~/Android/Sdk/platform-tools$ ./adb devices
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
List of devices attached

[email protected]:~/Android/Sdk/platform-tools$

lsusb внутри контейнера выводит список устройств:

[email protected]:~$ 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 --version
Docker version 1.5.0, build a8a31ef

В чем может быть проблема?

Ответ 1

Я не думаю, что демон ADB, работающий на устройстве, может быть подключен к двум серверам ADB. Попробуйте отключить его от 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

На случай, если кто-то захочет сделать это с нуля, я написал сообщение в блоге:

Как подключить устройства ADB к контейнеру Linux

Ответ 3

Это не отвечает на точный вопрос, который вы задавали, но отвечает на то, что вы пытались выполнить - подключение к устройству Android, подключенному к хосту докера, из клиента adb, работающего внутри контейнера докера. Я включаю это для тех, кто пытается сделать то же самое (как я).

Клиент adb поддерживает -H которая сообщает ему, где найти сервер adb для подключения. Docker поддерживает имя хоста "host.docker.internal", которое всегда сопоставляется с IP-адресом хоста докера. Предполагая, что ваше устройство подключено к док-хосту, вы можете сделать следующее, чтобы ваш контейнерный клиент adb подключился к серверу adb, запущенному на хосте докера:

adb -H host.docker.internal devices

Достигает цели без необходимости подключения портов USB.

Ссылка: https://developer.android.com/studio/command-line/adb

Обновление: я недавно узнал, что host.docker.internal поддерживается только в Docker для Mac в версиях 18.0 и выше.

Ответ 4

Это лучший способ сделать это, который будет работать, даже если вы отключите/подключите устройство после запуска контейнера http://marc.merlins.org/perso/linux/post_2018-12-20_Accessing-USB-Devices-In- Docker-ttyUSB0-DEV-шины USB - для быстрой загрузки-adb_--без помощи-privileged.html

В основном вы должны использовать devices.allow в cgroup, чтобы разрешить все символьные устройства этого старшего числа

Ответ 5

Простите за оффтоп. Но я не могу ответить на этот вопрос, поэтому я записываю его здесь.

Я использую Ubuntu: 18.04 и попытался подключить свой Samsung 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. После перезапуска сервера ADB внутри контейнера Docker И уничтожения сервера ADB на хост-компьютере. Я обнаружил, что на экране смартфона появился диалог подтверждения!

Так что на хост-компьютере проблема была в каталоге .android, я думаю. Просто переместите его в .android-backup. Следующая команда adb start-server создаст новую. Также я заменил папку platform-tools на самую последнюю

Ответ 6

Запуск с только --privileged -v /dev/bus/usb:/dev/bus/usb не работал для меня. Я попытался перенаправить порт прослушивания демона adb, используя -p 5037:5037, но это тоже не помогло.

Это сработало только после того, как я добавил --net host. Это означает, что сетевые интерфейсы хост-машины открыты для докера, поэтому используйте его, если у вас все в порядке. Возможно есть больше портов, которые должны были быть переданы кроме 5037....

Ответ 7

Обновить:

Я закончил тем, что использовал --privileged и -v для сопоставления всего /dev/bus/usb и исправления adb, чтобы принять одну переменную среды для указания корневого дерева USB-устройств - /dev/bus/usb/001 и т.д.

Это позволило нам использовать разные шины USB для разных контейнеров для разных групп одного и того же телефона, а другой патч переменной среды позволял использовать разные списки VID: PID для разных типов телефонов.


Мы пытаемся выделить разные шины USB для разных контейнеров Docker, на которых работают клиенты TeamCity.

Каждому контейнеру требуется установка ANDROID_ADB_SERVER_PORT для другого порта (потому что мы не используем сегрегированную сеть).

Хост-машина не может запустить adbd, потому что только один adbd может общаться с телефоном в любой момент времени.

Каждый контейнер получает один из /dev/bus/usb/xxx, поэтому мы можем подключить телефоны к определенным контейнерам.

Мы должны синхронизировать каталог /dev/bus/usb/xxx каждые несколько секунд, чтобы разрешить горячее подключение и перезагрузку - просто цикл оболочки на хосте, который запускает tar cf devxxx.tar/dev/bus/usb/xxx, docker cp для его передачи, затем docker exec для unntar внутри контейнера /tmp, diff для обнаружения mv -n узлов и mv -n для перемещения новых узлов.


Фактически, поскольку мы работаем в Linux, мы, вероятно, можем просто настроить сценарии udev, в соответствии с инструкциями по запуску сценария при подключении USB-устройства.