I might be mistaken, but I don’t understand how this tool or the practices in this article get you a truly repeatable build.
To me, having a repeatable build means you produce the same binary artifacts when you build your checked-in source code no matter when or on what machine you run the build on. But using a tool like Docker seems to already make this impossible. If a Dockerfile allows you to RUN apt-get install foo, then running that command at time T1 will give you a different answer than running at time T2.
RUN apt-get install foo
It seems to me like you can’t have real repeatability unless you have repeatable dependency semantics all the way down to the language level for each dependency manager you’re using. Tools like Blaze get around this by forcing you to use their own dependency management system that basically requires you to vendor everything, which guarantees repeatability. But I don’t see an analogous system in Earthly.
We debated ourselves a lot about what the right term is for this. From community feedback, we learned that there is a term for 100% deterministic builds: Reproducible builds. Earthly is not that. Bazel is. Earthly (and the practices that this guide talks about) has some consistency, but as you point out, it doesn’t get you all the way. We called this “repeatable builds” as an in-between term. The reasoning is that for many use-cases, it’s better if you are compatible with most open-source tooling, but are not 100% deterministic, rather than go all the way deterministic, but usability is heavily impacted.
No, you are not mistaken. Docker lets you RUN anything inside them, and so they are not reproducible by design. You could write Dockerfiles that are reproducible by not using some features (this is what Bazel does to ensure reproducibility when building Docker images).