Skip to content
README.md 8.04 KiB
Newer Older
Simo Kinnunen's avatar
Simo Kinnunen committed
# docker-adb

This repository contains a [Dockerfile](https://www.docker.io/) for the [Android Debug Bridge](http://developer.android.com/tools/help/adb.html). It gives you access to platform tools such as `adb` and `fastboot`.

## Changes

Karol Wrótniak's avatar
Karol Wrótniak committed
Android platform tools are automatically updated to the latest stable version on each docker image build.

* _2022-10-09_ Platform tools updated to `33.0.3`
* _2022-08-10_ Alpine updated to `3.16.2`
* _2022-08-10_ Alpine updated to `3.16.1`
* _2022-05-24_ Alpine updated to `3.16.0`
* _2022-04-06_ Alpine updated to `3.15.4`
* _2022-04-06_ Alpine updated to `3.15.3`
* _2022-03-23_ Alpine updated to `3.15.2`
* _2022-03-17_ Alpine updated to `3.15.1`
* _2021-11-24_ Alpine updated to `3.15.0`
* _2021-11-13_ Alpine updated to `3.14.3`
Karol Wrótniak's avatar
Karol Wrótniak committed
* _2021-10-02_ Glibc updated to `2.34-r0`
* _2021-10-02_ Alpine updated to `3.14.2`
* _2021-06-16_ Alpine updated to `3.14.0`
* _2021-04-15_ Alpine updated to `3.13.5`
* _2021-03-26_ Alpine updated to `3.13.3`
* _2021-02-18_ Alpine updated to `3.13.2`
* _2021-01-29_ Alpine updated to `3.13.1`
* _2021-01-15_ Alpine updated to `3.13.0`
* _2020-12-17_ Alpine updated to `3.12.3`
* _2020-12-11_ Alpine updated to `3.12.2`
Karol Wrótniak's avatar
Karol Wrótniak committed
* _2020-11-05_ Platform tools updated to `30.0.5`, glibc to `2.32-r0`
* _2020-10-22_ Alpine updated to `3.12.1`
* _2020-10-06_ Platform tools updated to `30.0.4`
* _2020-07-01_ Alpine updated to `3.12.0`, platorm tools updated to `29.0.6`
* _2016-07-02_ The image now uses [Alpine](https://hub.docker.com/_/alpine/) as the base image, making it way smaller. Furthermore, downloading the platform tools is now done in a more cunning way, further removing almost all dependencies and reducing image size. Only platform-tools are now included.
* _2016-07-02_ Due to internal ADB changes our previous start command no longer works in the latest version. The command has been updated, but if you were specifying it yourself, make sure you're using `adb -a -P 5037 server nodaemon`. Do NOT use the `fork-server` argument anymore.
* _2016-07-02_ The `.android` directory path has been fixed. Thanks to @alexislg2 for spotting it!
Simo Kinnunen's avatar
Simo Kinnunen committed

## Gotchas

* The container needs extended privileges for USB access
* The host's `/dev/bus/usb` must be mounted on the container

The container is preloaded with an RSA key for authentication, so that you won't have to accept a new key on the device every time you run the container (normally the key is generated on-demand by the adb binary). While convenient, it means that your device will be accessible over ADB to others who possess the key. You can supply your own keys by using `-v /your/key_folder:/root/.android` with `docker run`.

## Updating the platform tools manually

If you feel like the platform tools are out of date and can't wait for a new image, you can update the platform tools with the following command:

```sh
update-platform-tools.sh
```

It's in `/usr/local/bin` and therefore already in `$PATH`.
Simo Kinnunen's avatar
Simo Kinnunen committed
## Usage

There are various ways to use this image. Some of the possible usage patterns are listed below. It may sometimes be possible to mix them depending on the case. Also, you don't have to limit yourself to the patterns mentioned here. If you can find another way that works for you, go ahead.
Simo Kinnunen's avatar
Simo Kinnunen committed
### Pattern 1 - Shared network on the same machine (easy)

This usage pattern shares the ADB server container's network with ADB client containers.

Start the server:

docker run -d --privileged -v /dev/bus/usb:/dev/bus/usb --name adbd devicefarmer/adb
Simo Kinnunen's avatar
Simo Kinnunen committed
```

Then on the same machine:

docker run --rm -ti --net container:adbd devicefarmer/adb adb devices
Simo Kinnunen's avatar
Simo Kinnunen committed
docker run --rm -i --net container:adbd ubuntu nc localhost 5037 <<<000chost:devices
Simo Kinnunen's avatar
Simo Kinnunen committed
```

**Pros:**
Simo Kinnunen's avatar
Simo Kinnunen committed
* No port redirection required
* No need to look up IP addresses
* `adb forward` works without any tricks (but forwards will only be accessible to the client containers)
Simo Kinnunen's avatar
Simo Kinnunen committed

**Cons:**
Simo Kinnunen's avatar
Simo Kinnunen committed
* Cannot use bridged (or any other) network on the client container
* Only works if the server and client containers run on the same machine

### Pattern 2 - Host network (easy but feels wrong)

This usage pattern binds the ADB server directly to the host.

Start the server:

```
docker run -d --privileged --net host -v /dev/bus/usb:/dev/bus/usb --name adbd devicefarmer/adb
```

Then on the same machine:

```
docker run --rm -ti --net host devicefarmer/adb adb devices
docker run --rm -i --net host ubuntu nc localhost 5037 <<<000chost:devices
```

Or on another machine:

```
docker run --rm -ti sorccu/adb adb -H x.x.x.x -P 5037 devices
```

**Pros:**

* No port redirection required
* No need to look up IP addresses
* `adb forward` works without any tricks (and forwards are visible from other machines)
* No docker network overhead
* ADB server visible from other machines

**Cons:**

* ADB server visible from other machines unless the startup command is modified
* Client containers must always use host networking or know the machine's IP address

### Pattern 3 - Linked containers on the same machine (can be annoying)

This usage pattern shares the ADB server container's network with ADB client containers.

Start the server:

```
docker run -d --privileged -v /dev/bus/usb:/dev/bus/usb --name adbd sorccu/adb
```

Then on the same machine:

```
docker run --rm -ti --link adbd:adbd sorccu/adb \
  sh -c 'adb -H $ADBD_PORT_5037_TCP_ADDR -P 5037 devices'
```

**Pros:**

* No port redirection required
* No need to manually look up IP addresses
* `adb forward` works without any tricks (but forwards will only be accessible to the client containers over the designated IP)

**Cons:**

* Need to always pass the server IP to `adb` with `-H $ADBD_PORT_5037_TCP_ADDR`
* Need to be careful when running the container so that variables get replaced inside the container and not in the calling shell
* Only works if the server and client containers run on the same machine

### Pattern 4 - Remote client
Simo Kinnunen's avatar
Simo Kinnunen committed

This usage pattern works best when you want to access the ADB server from a remote host.

Start the server:

Simo Kinnunen's avatar
Simo Kinnunen committed
docker run -d --privileged -v /dev/bus/usb:/dev/bus/usb --name adbd -p 5037:5037 sorccu/adb
```

Then on the client host:

Fabio Rehm's avatar
Fabio Rehm committed
docker run --rm -ti sorccu/adb adb -H x.x.x.x -P 5037 devices
Simo Kinnunen's avatar
Simo Kinnunen committed
```

Where `x.x.x.x` is the server host machine.

**Pros:**
Simo Kinnunen's avatar
Simo Kinnunen committed
* Scales better (can use any number of hosts/clients)
* No network limitations

**Cons:**
Simo Kinnunen's avatar
Simo Kinnunen committed
* Need to be aware of IP addresses
* Higher latency
* You'll need to make other ports (e.g. from `adb forward`) accessible yourself
Simo Kinnunen's avatar
Simo Kinnunen committed

Simo Kinnunen's avatar
Simo Kinnunen committed
## Systemd units

Sample [systemd](https://www.freedesktop.org/wiki/Software/systemd/) units are provided in the [systemd/](systemd/) folder.

| Unit | Role | Purpose |
|------|------|---------|
| [adb-image.service](systemd/adb-image.service) | Support | Pulls the image from Docker Hub. |
| [adbd-container.service](systemd/adbd-container.service) | Support | Creates a container for the ADB daemon based on the adb image, but doesn't run it. |
| [adbd.service](systemd/adbd.service) | Primary | Runs the prepared ADB daemon container and makes sure it stays alive. |

This 3-unit configuration, while slightly complex, offers superior benefits such as incredibly fast start time on failure since everything has already been prepared for `adbd.service` so that it doesn't have to do any extra work. The adb image will only get pulled once at boot time instead of at every launch (or manually by calling `systemctl restart adb-image`, which will also restart the other units).

Copy the units to `/etc/systemd/system/` on your target machine.

Then, enable `adbd.service` so that it starts automatically after booting the machine:

```sh
systemctl enable adbd
```

Finally, either reboot or start the service manually:

```sh
systemctl start adbd
```

If you change the units, don't forget to run `systemctl daemon-reload` or they won't get updated.

Simo Kinnunen's avatar
Simo Kinnunen committed
## Thanks

* [Jérôme Petazzoni's post on the docker-user forum explaining USB device access](https://groups.google.com/d/msg/docker-user/UsekCwA1CSI/RtgmyJOsRtIJ)
* @sgerrand for [sgerrand/alpine-pkg-glibc](https://github.com/sgerrand/alpine-pkg-glibc)
* @frol for [frol/docker-alpine-glibc](https://github.com/frol/docker-alpine-glibc)
Simo Kinnunen's avatar
Simo Kinnunen committed

## License

See [LICENSE](LICENSE).