is there any way to speed up the development cycle with balena? I have a multi-container setup but usually only change one container at a time. Deploying changes to the device still takes ages (and right now the container executes one script which consists of 10 LoC, so build times should not be the issue here).
Things I tried to speed up the cycle:
do local pushes (still updates all containers and builds like forever)
switch from RasPi Zero (1st gen) to RasPi 4 during development to speed up the build times (but I except trouble when switching back to Zero for prod because they are very different hardware)
only install the bare minimum of dependencies that I need for the current problem I’m trying to solve
comment out any code that is not related to the current problem
I’m used to cycle times like in VueJS and similar frameworks, where any change in the code ACTUALLY does come into effect live (aka within seconds). With Balena, no matter what I try, it takes several minutes.
This is especially problematic, if I try to learn a new topic because the docs are only mediocre and the community small, so there’s a lot of trial and error and it easily takes days to e.g. get a new sensor running.
I use Balena because it has a modern approach to software deployment that is different from the traditional embedded world. Development with balena still throws me into the dark ages of microcontrollers and actually beyond, because actually writing code on the RasPi Host OS or deploying it via SSH to the host OS would be way faster that the balena apporach
Judging from your post, you are running into issues with local development because the containers/images are built on Pi Zero itself, which is pretty slow.
A first step is having a good look at your Dockerfile(s) and try to cut back on rebuilds as much as possible. There are some great tips here, like splitting up your builds into multiple stages.
When properly set up, you can make it so that only the source files you are changing are getting livepushed.
The initial push/build when doing the local development will probably still take forever though.
Ha, so true. That is without knowing your particular build process of course, but certainly for things like Vue in your example above, when I try a live push the device (RPI4) just crashes and the build fails.
I have been experimenting with an NFS Share to overcome some of these issues (can be pushed to the cloud). If you guys want to experiment with it too, would appreciate some feedback: GitHub - maggie44/docker-nfs: Serves the volume specified in the docker-compose file over NFS.. I haven’t added much in the way of docs, happy to throw some ideas out here on different ways to implement it if you haven’t got any in mind already.
The live push approach definitely should not be taking minutes to apply changes, I can imagine that’s very painful!
It might be worth mentioning that the order in which your Dockerfile(s) runs is important. You want the source files that you’re editing to be copied at as close to the end of the file as possible, because when changes are detected, all the directives prior to the line where the source file changes can be cached. All the directives afterwards are invalidated and rebuilt.
Another thing to look at are the livepush docs, where you can configure development environments as an alternative to your desired final configuration and even avoid restarting the container at all if the source file copy step is after the CMD.
Thanks everyone for your answers! Live-push is indeed fast if everything is already built and I just change the code (NodeJS in my case). But getting my dependencies running is a hell. Right now for example I’m trying to get pigpio npm dependency running. This is complicated enough directly on RasPi (because it uses a C library as dependency), but balenaOS adds a couple of layers of complexity and fiddling around with them triggers a complete rebuild. The live-push feature also seems to not shut down deamons correctly because I’m stuck with a pigpio error that seems to be deamon-related (still investigating though) which does not come up at the first start but after each live-push.
This is not the first time I’m going through this and every time after I found a working setup, it’s nice to use the live-push feature.
But if one takes software development seriously, they would not work on the machine at this time but mock out the libraries and develop code locally. So for the scenario in which I need a quick dev cycle the most (findig a working setup for my container), live-push is painstakingly slow. And for the scenario in which it is fast (developing my business logic), I don’t really need it
Thanks for your links, I’ll have a look into it and see where I have room for improvement.
Have you thought of splitting your docker image in two? We support something known as multi stage builds, and you can use that to split the part that doesn’t change that much into the first build, and then the other parts in the next stage