# Uso de USB/IP con Docker Desktop





USB/IP te permite compartir dispositivos USB a través de la red, a los cuales se puede acceder luego desde el interior de los contenedores de Docker. Esta página se centra en la compartición de dispositivos USB conectados a la máquina en la que ejecutas Docker Desktop. Puedes repetir el siguiente proceso para conectar y utilizar dispositivos USB adicionales según sea necesario.

> [!NOTE]
>
> Docker Desktop incluye controladores integrados para muchos dispositivos USB comunes, pero Docker no puede garantizar que todos los dispositivos USB posibles funcionen con esta configuración.

## Configuración y uso

### Paso uno: Ejecutar un servidor USB/IP

Para utilizar USB/IP, necesitas ejecutar un servidor USB/IP. Para esta guía, se utilizará la implementación proporcionada por [jiegec/usbip](https://github.com/jiegec/usbip).

1. Clona el repositorio.

    ```console
    $ git clone https://github.com/jiegec/usbip
    $ cd usbip
    ```

2. Ejecuta el ejemplo de dispositivo de interfaz humana (HID) emulado.

    ```console
    $ env RUST_LOG=info cargo run --example hid_keyboard
    ```

### Paso dos: Iniciar un contenedor de Docker privilegiado

Para conectar el dispositivo USB, inicia un contenedor de Docker privilegiado con el espacio de nombres PID configurado en `host`:

```console
$ docker run --rm -it --privileged --pid=host alpine
```

`--privileged` otorga al contenedor acceso total al host, y `--pid=host` le permite compartir el espacio de nombres de procesos del host.

### Paso tres: Entrar en el espacio de nombres de montaje del PID 1

Dentro del contenedor, entra en el espacio de nombres de montaje (mount namespace) del proceso `init` para obtener acceso a las herramientas USB/IP preinstaladas:

```console
$ nsenter -t 1 -m
```

### Paso cuatro: Utilizar las herramientas USB/IP

Ahora puedes utilizar las herramientas USB/IP tal como lo harías en cualquier otro sistema:

#### Listar dispositivos USB

Para listar los dispositivos USB exportables desde el host:

```console
$ usbip list -r host.docker.internal
```

Salida esperada:

```console
Exportable USB devices
======================
 - host.docker.internal
      0-0-0: unknown vendor : unknown product (0000:0000)
           : /sys/bus/0/0/0
           : (Defined at Interface level) (00/00/00)
           :  0 - unknown class / unknown subclass / unknown protocol (03/00/00)
```

#### Conectar un dispositivo USB

Para conectar un dispositivo USB específico, o el teclado emulado en este caso:

```console
$ usbip attach -r host.docker.internal -d 0-0-0
```

#### Verificar la conexión del dispositivo

Después de conectar el teclado emulado, comprueba el directorio `/dev/input` para localizar el nodo del dispositivo:

```console
$ ls /dev/input/
```

Ejemplo de salida:

```console
event0  mice
```

### Paso cinco: Acceder al dispositivo desde otro contenedor

Mientras el contenedor inicial permanece en ejecución para mantener el dispositivo USB operativo, puedes acceder al dispositivo conectado desde otro contenedor. Por ejemplo:

1. Inicia un contenedor con el dispositivo conectado.

    ```console
    $ docker run --rm -it --device "/dev/input/event0" alpine
    ```

2. Instala una herramienta como `evtest` para probar el teclado emulado.

    ```console
    $ apk add evtest
    $ evtest /dev/input/event0
    ```

3. Interactúa con el dispositivo y observa la salida.

    Ejemplo de salida:

    ```console
    Input driver version is 1.0.1
    Input device ID: bus 0x3 vendor 0x0 product 0x0 version 0x111
    ...
    Properties:
    Testing ... (interrupt to exit)
    Event: time 1717575532.881540, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7001e
    Event: time 1717575532.881540, type 1 (EV_KEY), code 2 (KEY_1), value 1
    Event: time 1717575532.881540, -------------- SYN_REPORT ------------
    ...
    ```

> [!IMPORTANT]
>
> El contenedor inicial debe permanecer en ejecución para mantener la conexión con el dispositivo USB. Salir del contenedor hará que el dispositivo deje de funcionar.


