So, recently i figured that i'd cook up a script that uses my webcam for motion detection, which i wrote more about here: DIY surveillance: motion detection with OpenCV and Python
And, after finishing it, i figured that packaging it inside of a Docker container would be the logical thing to do - i wouldn't need to mess around with virtual environments and could easily limit the amount of memory and CPU resources the script could use, in addition to taking advantage of the infrastructure that i already have.
Now, the weird bit about this particular container was that i'd need to somehow give it the access to the webcam that's available on the host. Docker Compose actually has a command to do just that:
devices:
- /dev/video0:/dev/video0
The problem is that Docker Swarm doesn't implement it for some reason and it is therefore ignored. Even the documentation says so:
And this is just one of the many directives that Docker itself supports, but for whatever reason Docker Compose doesn't, even if it uses Docker for running the containers:
Honestly, this is a massive pain in the behind, since not only does this mean that you cannot use Docker Compose for sharing devices, but also other functionality such as privileged containers.
I wouldn't mind if Docker Swarm would at least explain why this is a problem and fail with a helpful exit code/message, but instead it decides to scoot the problems under the rug and pretend that everything is fine.
Of course it isn't, so you'll just get problems in your script/app when you get to the code that needs to use the device:
Now, there are a few hacks around this, but they're... well, hacky.
For example, look at this one:
I am desperate, but i am not that desperate! It just goes on and on and on with cryptic commands which, while would probably achieve the desired result in some capacity, no longer can be deployed as a standalone YAML and therefore violate the concepts of container isolation from the host, since host configuration would be necessary in this case.
Then there is yet another hack around the problem:
Except that this one causes you to share the Docker socket with the host and run Docker commands directly. This kind of throws out the whole idea of Swarm actually managing the service state and getting information about its health, the logs and so on. Instead, you'd end up with a leaky abstraction, or have to write your own wrapper around the bits that'd be missing.
I think someone got a bit lazy when translating the Docker feature set support from Compose to Swarm.