I’m looking for any recommendations or wisdom around running multiple containers from a single image. The use case is this, I’m trying to process multiple independent streams of data on a single device, each requires slightly different configuration. I could have run this all single-process or multi-process-single-container, but the cleanliness of having each process containerized is very appealing as the logs are segregated and seems to play well with the control plane that balena offers, for example, starting and shutting some services independently and exposing that status in the dashboard.
But I have run into a few catches that make this rough.
Design
I’m using the multi-service approach in balena. There is no way to dynamically create services in balena. So I cannot simply scale the number of containers based on runtime configuration. This would be desirable in my case but isn’t possible currently. What I have resorted to, is creating a large number of services greater than I expect to use, in a docker-compose file and then idle/shutdown the unused ones. Does anyone have any better ideas around this?
Build Time
Things get interesting here. If I “balena push” a docker compose with say, 10 services, all with same “build” stanza in docker-compose, the builder tries to build the same image 10 times in parallel. This is impossibly long for local mode on a pi4 and I image I’d be abusing balena’s build servers, especially if I scale to 20 or more containers. If I modify the docker compose to have one service, “balena push”, then add them back in docker-compose, and use the cache, it works, but I still have a time bomb of dozens of builds starting if I make a cache-invalidating change to the service.
I’ve resorted to completely side stepping the balena commands to build the release, just building my image with “docker build” and pushing to a docker hub repo, and then just using that pre-built image in each service’s “image” stanza. This works just fine, but because I’m a bit outside the balena ecosystem there is a bit of friction as I can’t use things like Dockerfile.template and can’t use the balena build servers for native builds, only putting together the docker-compose. Which also runs very long for not doing any building as it seems to calculate diffs for each identical image.
Any ideas on how to do this better?
Run Time
The services check if they have a device-service configuration, if not they “sleep”. Just sleeping works ok, but I dislike that I can’t simply see the services that are shutdown as off in the service list in balena dashboard. So, I tried to make them self-destruct via the supervisor api. However, I get some pretty wild results. If the service calls the stop-service api in the supervisor, it starts bouncing in a restart loop as balena keeps trying to restart the service. With 10 or more services this is totally unusable with several containers constantly bouncing and using resources. If I set the docker-compose restart stanza to “unless-stopped” this seems to stop the bouncing madness but then containers that have actually failed stop forever. The goal is that I want service that self shutdown to stay down and everything else to bounce back to running on failure. Is this possible in balena currently?