Docker build-arg for BALENA_MACHINE_NAME instead of using Dockerfile.template

I’m developing an application that spans multiple device types / architectures.

I’m using a Dockerfile.template like this:

FROM wlisac/%%BALENA_MACHINE_NAME%%-swift:5.0

# do stuff

This works great with BalenaCloud, but one downside to this approach is that this template won’t build locally via docker build:

$ docker build -f Dockerfile.template .
Step 1/8 : FROM wlisac/%%BALENA_MACHINE_NAME%%-swift:5.0

invalid reference format: repository name must be lowercase

A workaround is to use a build-arg in the Dockerfile.template like this:

ARG BASE_IMAGE=wlisac/%%BALENA_MACHINE_NAME%%-swift:5.0

FROM $BASE_IMAGE

# do stuff

And then you can build the Dockerfile locally like this:

$ docker build -f Dockerfile.template --build-arg BASE_IMAGE=wlisac/raspberrypi3-swift:5.0 .

This is a decent workaround, but I’m wondering if Balena would consider sending build args for BALENA_MACHINE_NAME and other variables that are often used in templates when building via Balena.

This would allow a plain Dockerfile like this to work locally and via BalenaCloud without using a template:

Dockerfile

ARG BALENA_MACHINE_NAME=raspberrypi3

FROM wlisac/$BALENA_MACHINE_NAME-swift:5.0

# do stuff

I’m not sure of the origin of Balena’s Dockerfile.template, but it’s possible that Allow ARG in FROM makes templating less necessary.

Would love to know what others think of this idea.

Cheers,
Will

Hey @wlisac,

We’ve actually spoken about this in the past, and the reason that we didn’t is because this used to cause a docker build failure when the argument was not read, more on that here: https://github.com/moby/moby/issues/26249

That no longer is the case, and unconsumed build arguments now only cause an error (not ideal, but usable).

I can raise this for internal discussion to see what comes of it, but in the meantime, it’s possible to use balena build for this. This will build an entire docker-compose project (or a single Dockerfile(.template)) project, whilst also resolving any of these balena specific variables. The builds produce images on your local docker daemon, just like running (docker build ...).

Thanks for the idea and feedback!

Hi, was curious about this topic.

I’m currently looking to do basic development on several containers using fincm3-python:3.8-run and they run significantly faster on my laptop then in local mode using live push.

I’ve used the docker desktop emulator to run arm32 but I’ve had even better performance running genericx86-64-extbalena base images. I would like to use a docker-compose.override.yml for development to switch the fincm3 for genericx86 but as the poster above mentioned the only way to really do this with is to declare a build arg both in the compose file and before the FROM argument in the containers dockerfile.

My primary use case is TDD for several containers acting as microservices that do not interact with hardware but rather connect with our cloud API and other internal logic workers. Pytest performance is approximately ~5x faster on my laptop using genericx86 as apposed to running on via livepush and I no longer need to have a balena device in hand which is great for on the go development.

Is there a better workflow to go about this and/or is the ARG before FROM dockerfile support being considered? My alternate thought is to duplicate dockerfiles for each container and use the dockerfile build argument to point to a production dockerfile that use the %%BALENA_MACHINE_NAME%% and use override.yml to point to an x86 dockerfile for local laptop development.

Any thoughts on these ideas greatly appreciated!

Hey there

Pytest performance is approximately ~5x faster on my laptop using genericx86 as apposed to running on via livepush and I no longer need to have a balena device in hand which is great for on the go development.

Can you please elaborate on how you are developing with a genericx64 device locally?

Perhaps you can have 2 fleets with different device types and you would use the genericx86-64-ext fleet for developing.

You can add a VM or even run a container on your laptop and that would act as a genericx86-64-ext device. You can even livepush to it.

Here are some links you might find helpful:

Thanks