docker / buildx

Docker CLI plugin for extended build capabilities with BuildKit
Apache License 2.0
3.5k stars 472 forks source link

bake-hcl: add mechanism to reference the current target name #1203

Open tnaroska opened 2 years ago

tnaroska commented 2 years ago

I have a bake hcl file defining multiple targets which share some common configuration (e.g. build-args, target platform, secrets, ...). To minimize duplication I have moved these into an abstract _base target and use the inherits attribute to import the shared values into each leaf traget.

This works great in general but fails for attributes like cache-from, tags which require their unique values for each lead target as shown in the example below.

target "_base" {
    args = {
        CORE_BRANCH  = CORE_BRANCH
        CORE_VERSION = CORE_VERSION
        BUILDKIT_SYNTAX = docker/dockerfile:1.4
    }
    cache-to  = ["type=inline"]
    secret    = ["id=artifactory_user,env=ARTIFACTORY_USER", "id=artifactory_pass,env=ARTIFACTORY_API_TOKEN"]
    platforms = ...
}

target "image1" {
    dockerfile = "image1/Dockerfile"
    cache-from = "myrepo/image1"
    tags = "myrepo/image1"
    inherits = ["_base"]
}

target "image2" {
    dockerfile = "image2/Dockerfile"
    cache-from = "myrepo/image2"
    tags = "myrepo/image2"
    inherits = ["_base"]
}
... more targets ...

The ask is to have a special hcl variable or function to reference the current target's name (think of $@ in a makefile). The same file could then be rewritten:

target "_base" {
    args = {
        CORE_BRANCH  = CORE_BRANCH
        CORE_VERSION = CORE_VERSION
        BUILDKIT_SYNTAX = docker/dockerfile:1.4
    }
    cache-to  = ["type=inline"]
    secret    = ["id=artifactory_user,env=ARTIFACTORY_USER", "id=artifactory_pass,env=ARTIFACTORY_API_TOKEN"]
    platforms = ...

    # using ${target} to reference target name. actual syntax TBD
    cache-from = "myrepo/${target}"
    tags = "myrepo/${target}"
}

target "image1" {
    dockerfile = "image1/Dockerfile"
    inherits = ["_base"]
}

target "image2" {
    dockerfile = "image2/Dockerfile"
    inherits = ["_base"]
}

Environment:

buildx   v0.8.2
buildkit v0.10.3
tnaroska commented 2 years ago

possibly similar to https://github.com/docker/buildx/issues/445

iraadit commented 2 years ago

I would be interested by the same functionality

kipters commented 1 year ago

I'd be interested too

sergeykad commented 11 months ago

I believe this feature is essential for making Bake HCL more readable and maintainable. As you can see here, the lack of this feature makes the configuration file twice as large and requires a lot of duplication. If you also count the duplicated dockerfile property, the file is three times larger than it would be otherwise.

jedevc commented 11 months ago

With the way the HCL code is currently structured, it might not be that hard to add a new current property or similar that maps to the current block being evaluated (the refactor to allow targets and groups fields has done most of the heavily lifting I think).

I think the desired syntax would probably be a new top-level field called current (targets.current would be nice, but then what if there's a target called current). I'd rather that than target, since then it would work the same in groups and any other future block types.

firas-hojirat commented 7 months ago

any updates? what's blocking this? what can I do to help push this further? I'm really interested in this, as it can reduce a lot of duplication especially for the cache-to/from and tags fields

firas-hojirat commented 3 months ago

@tonistiigi @crazy-max @jedevc @thaJeztah

thompson-shaun commented 1 month ago

@colinhemmings

tonistiigi commented 1 month ago

targets.current to get the current name seems like a fine approach.

We don't have this prioritized atm, but if anyone from the community can make a PR, then let us know.

jsternberg commented 1 week ago

This may be difficult to do without a substantial change in some of the fields. The main problem is that the HCL expression expansion happens before the inherits attribute is evaluated to merge the contexts.

It might be possible for us to evaluate the inherits earlier and I can look into that. At the same time, the use case seems to relate similarly to the matrix attribute.

tonistiigi commented 5 days ago

Changing the order of expression expansion and inherits would break cases like:

variable "FOO" {
}

target "main" {
  inherits = [FOO]
}

or inherits = functioncall() etc.