cloud66-oss / habitus

A build flow tool for Docker.
https://help.cloud66.com/habitus/
Apache License 2.0
1.36k stars 91 forks source link

Dockerfile.generated race with same Dockerfile and different build args #113

Open grugnog opened 5 years ago

grugnog commented 5 years ago

build.yml looks something like:

build:
  version: 2016-03-14 # version of the build schema.
  steps:
    v1:
      name: v1
      dockerfile: Dockerfile
      args:
        version: 1
    v2:
      name: v2
      dockerfile: Dockerfile
      args:
        version: 2

What happens is that the Dockerfile.generated is the same filename and path. Both builds proceed in parallel (using whichever file was created last). As soon as the first build finishes the Dockerfile.generated is removed and so the second build errors with "Build for step v2:latest failed due to remove dir/Dockerfile.generated: no such file or directory".

I think the solution for this would be to either encode the build args in the filename for Dockerfile.generated (probably in the form of a hash) or generate a random token to the file and track that through the lifecycle of the build. The latter seems like the simpler approach, since it seems likely there is other data (perhaps the context directory, for example) that could affect the build and would need to be included in the hash.

grugnog commented 5 years ago

For anyone else with the same issue, it seems that you can work around this by using depends_on to ensure they build in serial and don't step on each others toes.

khash commented 5 years ago

Thank you @grugnog for the suggestion. It makes sense to use depends_on to avoid a race condition, however I'd like to know what you need to achieve so probably we can make changes to accomodate that without serialising the builds.

grugnog commented 5 years ago

I think the use case described in my example is probably a good one to work from. We want to allow a single Dockerfile to build different versions of the same program, so (rather than duplicate the Dockerfiles or build some templating system) we use build args to inject the version we want to build. In this case the 2 builds are totally independent, so the depends_on is really just a workaround - a better result would be to have the Dockerfile.generated file name include a hash or random token, so that the builds can be run in parallel.