How do I force resin to rebuild my Dockerfile

docker
#1

Hi,

I currently switched to Travis CI for automated build process, and after every successful build, the docker image is pushed to docker cloud with latest tag (e.g. myusername/my-docker-image:latest)

On my resin repo, I have a simple dockerfile containing:

FROM myusername/my-docker-image:latest

CMD /bin/bash

which is already pushed to resin git repo and resin has successfully built, downloaded, installed and run a container inside my device.

My problem is: everytime travis has done its building steps and push docker image to docker cloud, I need to notify resin to re-pull myusername/my-docker-image:latest again OR re-build the docker image again (without any cache). I’ve been looking for the solution on google, official docs… but it seems that no one has the same problem.

My current work around (based on this idea) is to modify my dockerfile to

FROM myusername/my-docker-image:latest

ENV version 1.0

CMD /bin/bash

and bump version every time travis CI has done building docker image, to manually trigger resin to rebuild its image.

Any other more optimal solution, please ?

#2

The environment variable is a common way to force changes to the Dockerfile, though it will still cache the first step like that.

Generally forcing rebuild could be done by pushing to the resin-nocache branch, ie git push resin <orignbranch>:resin-nocache (where your originbranch is probably not master, if you are using CI, right? But any origin branchname works, just need to specify. Might also need to --force, if you are different branches all the time (but that probably you already do).

One thing to note, though, that currently one git revision is only built once, so if you have a successful push of a git revision (either to master as regular cache build or to resin-nocache as non-cached build), it will not built again with the same git revision. In that case you would need to add any changes to the commit that you’d like to rebuild (either add an empty commit on top, or update the last commit with --amend which should change the revision SHA). Hope it makes sense, or let me know if it’s too confusing as I explained :slight_smile:

#3

It’s good to know that we can use nocache branch for that purpose, I wish that it’s would be mentioned somewhere in the docs.

But I don’t think it would be efficiently used for my purpose as I just want resin.io to rebuild my unchanged dockerfile since as you said, one git revision is only built no more than once.

And you told about environment variable which may help to force changes to the Dockerfile. Can I have any information about this? I thought that env variable is just for runtime and not for build-time. In fact, I was always wondering that how can I pass any build arguments to the docker build command? The environment variable setting in the dashboard seems not to do the mentioned work.

#4

Yes, we are working on documenting it better, and there are a couple of builder features coming in that will be good to publicise wider. Taking a note of it, and will do.

I think there are multiple things to clarify:

  • If you use latest for the image, in normal Docker that is frequently cached, and that’s the intended behaviour, when it means one doesn’t care about the explicit version of the image to pull. If you want to care about the explicit image to pull, then use a specific tag there. You could for example version your dockerfile, and then pull in the specific version in your resin Dockerfile (so you always know what version is running, and caching is solved)
  • if I read the original issue correctly, the caching is the main thing for you, and that is generally the no-cache branch helps
  • the Env variables there are not used for the build, they are just a simple way to modify the Dockerfile, and force docker to rebuild everything after that point. So in your case that wouldn’t do the proper thing either, as latest might or might not be cached.
  • currently there’s no way to pass build arguments to docker on resin. If you’d like to build things differently, you would have to use the resin-cli and do local builds (instead of building on the resin servers). Build time variables are on the roadmap but not quite there yet.

So I guess the most reliable way in your setup would be versioning your own dockerfile (and moving away from using :latest), in which case you will need to update the resin Dockerfile still, but it do caching exactly as you expect (and as a bonus, you will know exactly what version is deployed)

#5

Thank you for your details reply. I am very excited to know that the build time variables will come soon.

So I better stick on not using :latest tag anymore and using a specific version tag instead.

1 Like
#6

Hi @imrehg – any chance this has changed since 2017?

I’m looking for a way to use balena push and force a re-pull of the base image.

Something like balena push MyApp --pull or balena push <local-device-ip> --pull? I haven’t been able to find a way to accomplish this so far.

Cheers,
Will

#8

To expand on my use case a bit – I’m iterating on a base image and attempting to validate it against some of my existing balena projects.

Often I’m doing this against a device in local mode, so my workaround for local mode is to explicitly pull the latest image via docker and then push via balena:

docker -H=<local-device-ip>:2375 pull <image-name>
balena push <local-device-ip> --nocache

Unfortunately, I don’t know of a workaround for the cloud builders.

#9

Hey @wlisac,
We currently do not support something like this in our backend.
Also let me clarify that balena push <appName> --nocache only ignores previously built intermediate layers of your build, but doesn’t force a refetch of the images, like your local docker pull does.
I’ve opened an internal issue to track this and consider providing an implementation for that use case.

On the other hand I would like to suggest you to avoid using the latest tag on production applications.
First of all, it doesn’t allow for reproducible builds of your app, since the latest tag could be pointing to different images, depending on the time that the image was pulled on each machine.
Moreover, if in any case an image is published w/o a specific tag, then it becomes the new latest, which can cause issues if the base image’s author just forgets to specify a tag during a publish.

Kind regards,
Thodoris

1 Like
#11

Thanks for the input and for opening an internal issue :slight_smile: It makes sense to me to avoid using latest in a production application.

To add some details to my use case – I’m working on creating a base image language stack for balena. It’s similar to the existing language stacks for node, python, etc, but for the Swift programming language.

The challenge I’ve run in to is that I’ve occasionally “burned” a couple of tags that I’d like to use by accidentally pushing bad images to these tags.

For example:

Balena has a base image like balenalib/raspberrypi3-node:10.10 and I have a base image like wlisac/raspberrypi3-swift:5.0.

Once a bad image is pushed to that tag, it’s “burned” as a bad tag until the cloud builders (eventually?) purge the cached image.

Having a way to request that the cloud builders invalidate an image / tag would be helpful, or even getting some (implementation detail) insights into how long a “base” image is cached for would be awesome.

Sorry for the relatively obscure use case / question :slight_smile:

Best,
Will

#12

We do usually build with a --pull flag, which should cause base images to at least be attempted to be downloaded again, I’ll check the source to see if something has changed there.

Edit: We definitely still apply this flag, so I’m not sure why you’re seeing a different behaviour, the description is:

–pull Always attempt to pull a newer version of the image

Perhaps a docker bug? Do you ensure the new image is pushed before starting the build etc?