Add configuration for docker executor to add devices for services
Description
Problem
Host devices cannot be mounted in services. The runner config allows us to mount devices to the actual job container but services do not appear to inherit this. We have a very complex emulator running in a container and its extremely difficult to build everything into one image running the tests. So we use the emulator as a service.
Use case
I build emulators that are distributed as docker images. They work as services
running in the docker executor but they're extremely slow without hardware
acceleration. I need to mount /dev/kvm/ and /dev/dri from the host to enable
hardware acceleration. I would need to configure a docker executor to specify
devices for services and might also need to specify the images which will have the
devices mounted.
Benefit
For my Android emulators it cuts boot time from 1-9 minutes to 5 seconds and
every other performance metric is improved as well. /dev/kvm is really
important for the QEMU based emulators we run. Currently CI options involve
moving our testing to another commercial service, GenyMotion Cloud
(https://www.genymotion.com/cloud/) because the boot lag without /dev/kvm
is a non-starter.
There is also the possibility of using /dev/usb. Devices being run in
"device farms" are typically accessed over USB. I have device farm but am
no where near realizing how to use it with Gitlab-CI/gitlab-runner without
this kind of support.
Goals
Be able to use host devices in services.
Proposal
Add a mapping of <image name pattern> = [device, ...], so a
map[string][]string. This mapping would allow only specific images to have
specific devices mounted.
I cannot think of any specific cases where mounting a device to an arbitrary container would have adverse effects, i.e. device/driver conflict of some sort, but this method would avoid it entirely.
Allowing device access only to specific images running as services is also more secure. Exposing devices only to trusted images that users cannot run arbitrary code in is a lot safer than devices exposed to the job container.
[runners.docker]
[runners.docker.service_devices]
"emulator:*" = ["/dev/kvm", "/dev/dri"]