From b9007be9a2ce46e628ed5a5da20786503f86dd11 Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Fri, 25 Nov 2022 12:32:21 +0100 Subject: [PATCH] build: move upstream bake docs in docs repo Signed-off-by: CrazyMax --- _config.yml | 3 - build/customize/bake/build-contexts.md | 76 +++- build/customize/bake/compose-file.md | 273 ++++++++++++- build/customize/bake/configuring-build.md | 218 ++++++++++- build/customize/bake/file-definition.md | 442 +++++++++++++++++++++- build/customize/bake/hcl-funcs.md | 329 +++++++++++++++- build/customize/bake/index.md | 38 +- 7 files changed, 1358 insertions(+), 21 deletions(-) diff --git a/_config.yml b/_config.yml index df2413dd5c..9dc488d11a 100644 --- a/_config.yml +++ b/_config.yml @@ -191,9 +191,6 @@ fetch-remote: default_branch: "master" ref: "master" paths: - - dest: "build/customize/bake" - src: - - "docs/manuals/bake/**" - dest: "build/building" src: - "docs/manuals/drivers" diff --git a/build/customize/bake/build-contexts.md b/build/customize/bake/build-contexts.md index 556900ee52..b40fd7e001 100644 --- a/build/customize/bake/build-contexts.md +++ b/build/customize/bake/build-contexts.md @@ -3,7 +3,77 @@ title: "Defining additional build contexts and linking targets" keywords: build, buildx, bake, buildkit, hcl redirect_from: - /build/bake/build-contexts/ -fetch_remote: - line_start: 2 - line_end: -1 --- + +In addition to the main `context` key that defines the build context each target +can also define additional named contexts with a map defined with key `contexts`. +These values map to the `--build-context` flag in the [build command](../../../engine/reference/commandline/buildx_build.md#build-context). + +Inside the Dockerfile these contexts can be used with the `FROM` instruction or `--from` flag. + +The value can be a local source directory, container image (with `docker-image://` prefix), +Git URL, HTTP URL or a name of another target in the Bake file (with `target:` prefix). + +## Pinning alpine image + +```dockerfile +# syntax=docker/dockerfile:1 +FROM alpine +RUN echo "Hello world" +``` + +```hcl +# docker-bake.hcl +target "app" { + contexts = { + alpine = "docker-image://alpine:3.13" + } +} +``` + +## Using a secondary source directory + +```dockerfile +# syntax=docker/dockerfile:1 +FROM scratch AS src + +FROM golang +COPY --from=src . . +``` + +```hcl +# docker-bake.hcl +target "app" { + contexts = { + src = "../path/to/source" + } +} +``` + +## Using a result of one target as a base image in another target + +To use a result of one target as a build context of another, specity the target +name with `target:` prefix. + +```dockerfile +# syntax=docker/dockerfile:1 +FROM baseapp +RUN echo "Hello world" +``` + +```hcl +# docker-bake.hcl +target "base" { + dockerfile = "baseapp.Dockerfile" +} + +target "app" { + contexts = { + baseapp = "target:base" + } +} +``` + +Please note that in most cases you should just use a single multi-stage +Dockerfile with multiple targets for similar behavior. This case is recommended +when you have multiple Dockerfiles that can't be easily merged into one. diff --git a/build/customize/bake/compose-file.md b/build/customize/bake/compose-file.md index 9accdcbf67..90b817e522 100644 --- a/build/customize/bake/compose-file.md +++ b/build/customize/bake/compose-file.md @@ -3,7 +3,274 @@ title: "Building from Compose file" keywords: build, buildx, bake, buildkit, compose redirect_from: - /build/bake/compose-file/ -fetch_remote: - line_start: 2 - line_end: -1 --- + +## Specification + +Bake uses the [compose-spec](../../../compose/compose-file/index.md) to +parse a compose file and translate each service to a [target](file-definition.md#target). + +```yaml +# docker-compose.yml +services: + webapp-dev: + build: &build-dev + dockerfile: Dockerfile.webapp + tags: + - docker.io/username/webapp:latest + cache_from: + - docker.io/username/webapp:cache + cache_to: + - docker.io/username/webapp:cache + + webapp-release: + build: + <<: *build-dev + x-bake: + platforms: + - linux/amd64 + - linux/arm64 + + db: + image: docker.io/username/db + build: + dockerfile: Dockerfile.db +``` + +```console +$ docker buildx bake --print +``` +```json +{ + "group": { + "default": { + "targets": [ + "db", + "webapp-dev", + "webapp-release" + ] + } + }, + "target": { + "db": { + "context": ".", + "dockerfile": "Dockerfile.db", + "tags": [ + "docker.io/username/db" + ] + }, + "webapp-dev": { + "context": ".", + "dockerfile": "Dockerfile.webapp", + "tags": [ + "docker.io/username/webapp:latest" + ], + "cache-from": [ + "docker.io/username/webapp:cache" + ], + "cache-to": [ + "docker.io/username/webapp:cache" + ] + }, + "webapp-release": { + "context": ".", + "dockerfile": "Dockerfile.webapp", + "tags": [ + "docker.io/username/webapp:latest" + ], + "cache-from": [ + "docker.io/username/webapp:cache" + ], + "cache-to": [ + "docker.io/username/webapp:cache" + ], + "platforms": [ + "linux/amd64", + "linux/arm64" + ] + } + } +} +``` + +Unlike the [HCL format](file-definition.md#hcl-definition), there are some +limitations with the compose format: + +* Specifying variables or global scope attributes is not yet supported +* `inherits` service field is not supported, but you can use [YAML anchors](https://docs.docker.com/compose/compose-file/#fragments){:target="_blank" rel="noopener" class="_"} + to reference other services like the example above + +## `.env` file + +You can declare default environment variables in an environment file named +`.env`. This file will be loaded from the current working directory, +where the command is executed and applied to compose definitions passed +with `-f`. + +```yaml +# docker-compose.yml +services: + webapp: + image: docker.io/username/webapp:${TAG:-v1.0.0} + build: + dockerfile: Dockerfile +``` + +``` +# .env +TAG=v1.1.0 +``` + +```console +$ docker buildx bake --print +``` +```json +{ + "group": { + "default": { + "targets": [ + "webapp" + ] + } + }, + "target": { + "webapp": { + "context": ".", + "dockerfile": "Dockerfile", + "tags": [ + "docker.io/username/webapp:v1.1.0" + ] + } + } +} +``` + +> **Note** +> +> System environment variables take precedence over environment variables +> in `.env` file. + +## Extension field with `x-bake` + +Even if some fields are not (yet) available in the compose specification, you +can use the [special extension](../../../compose/compose-file/index.md#extension) +field `x-bake` in your compose file to evaluate extra fields: + +```yaml +# docker-compose.yml +services: + addon: + image: ct-addon:bar + build: + context: . + dockerfile: ./Dockerfile + args: + CT_ECR: foo + CT_TAG: bar + x-bake: + tags: + - ct-addon:foo + - ct-addon:alp + platforms: + - linux/amd64 + - linux/arm64 + cache-from: + - user/app:cache + - type=local,src=path/to/cache + cache-to: + - type=local,dest=path/to/cache + pull: true + + aws: + image: ct-fake-aws:bar + build: + dockerfile: ./aws.Dockerfile + args: + CT_ECR: foo + CT_TAG: bar + x-bake: + secret: + - id=mysecret,src=./secret + - id=mysecret2,src=./secret2 + platforms: linux/arm64 + output: type=docker + no-cache: true +``` + +```console +$ docker buildx bake --print +``` +```json +{ + "group": { + "default": { + "targets": [ + "aws", + "addon" + ] + } + }, + "target": { + "addon": { + "context": ".", + "dockerfile": "./Dockerfile", + "args": { + "CT_ECR": "foo", + "CT_TAG": "bar" + }, + "tags": [ + "ct-addon:foo", + "ct-addon:alp" + ], + "cache-from": [ + "user/app:cache", + "type=local,src=path/to/cache" + ], + "cache-to": [ + "type=local,dest=path/to/cache" + ], + "platforms": [ + "linux/amd64", + "linux/arm64" + ], + "pull": true + }, + "aws": { + "context": ".", + "dockerfile": "./aws.Dockerfile", + "args": { + "CT_ECR": "foo", + "CT_TAG": "bar" + }, + "tags": [ + "ct-fake-aws:bar" + ], + "secret": [ + "id=mysecret,src=./secret", + "id=mysecret2,src=./secret2" + ], + "platforms": [ + "linux/arm64" + ], + "output": [ + "type=docker" + ], + "no-cache": true + } + } +} +``` + +Complete list of valid fields for `x-bake`: + +* `cache-from` +* `cache-to` +* `contexts` +* `no-cache` +* `no-cache-filter` +* `output` +* `platforms` +* `pull` +* `secret` +* `ssh` +* `tags` diff --git a/build/customize/bake/configuring-build.md b/build/customize/bake/configuring-build.md index 156750c519..2487b205fd 100644 --- a/build/customize/bake/configuring-build.md +++ b/build/customize/bake/configuring-build.md @@ -3,7 +3,219 @@ title: "Configuring builds" keywords: build, buildx, bake, buildkit, hcl, json redirect_from: - /build/bake/configuring-build/ -fetch_remote: - line_start: 2 - line_end: -1 --- + +Bake supports loading build definition from files, but sometimes you need even +more flexibility to configure this definition. + +For this use case, you can define variables inside the bake files that can be +set by the user with environment variables or by [attribute definitions](#global-scope-attributes) +in other bake files. If you wish to change a specific value for a single +invocation you can use the `--set` flag [from the command line](#from-command-line). + +## Global scope attributes + +You can define global scope attributes in HCL/JSON and use them for code reuse +and setting values for variables. This means you can do a "data-only" HCL file +with the values you want to set/override and use it in the list of regular +output files. + +```hcl +# docker-bake.hcl +variable "FOO" { + default = "abc" +} + +target "app" { + args = { + v1 = "pre-${FOO}" + } +} +``` + +You can use this file directly: + +```console +$ docker buildx bake --print app +``` +```json +{ + "group": { + "default": { + "targets": [ + "app" + ] + } + }, + "target": { + "app": { + "context": ".", + "dockerfile": "Dockerfile", + "args": { + "v1": "pre-abc" + } + } + } +} +``` + +Or create an override configuration file: + +```hcl +# env.hcl +WHOAMI="myuser" +FOO="def-${WHOAMI}" +``` + +And invoke bake together with both of the files: + +```console +$ docker buildx bake -f docker-bake.hcl -f env.hcl --print app +``` +```json +{ + "group": { + "default": { + "targets": [ + "app" + ] + } + }, + "target": { + "app": { + "context": ".", + "dockerfile": "Dockerfile", + "args": { + "v1": "pre-def-myuser" + } + } + } +} +``` + +## From command line + +You can also override target configurations from the command line with the +[`--set` flag](../../../engine/reference/commandline/buildx_bake.md#set): + +```hcl +# docker-bake.hcl +target "app" { + args = { + mybuildarg = "foo" + } +} +``` + +```console +$ docker buildx bake --set app.args.mybuildarg=bar --set app.platform=linux/arm64 app --print +``` +```json +{ + "group": { + "default": { + "targets": [ + "app" + ] + } + }, + "target": { + "app": { + "context": ".", + "dockerfile": "Dockerfile", + "args": { + "mybuildarg": "bar" + }, + "platforms": [ + "linux/arm64" + ] + } + } +} +``` + +Pattern matching syntax defined in [https://golang.org/pkg/path/#Match](https://golang.org/pkg/path/#Match){:target="_blank" rel="noopener" class="_"} +is also supported: + +```console +$ docker buildx bake --set foo*.args.mybuildarg=value # overrides build arg for all targets starting with "foo" +$ docker buildx bake --set *.platform=linux/arm64 # overrides platform for all targets +$ docker buildx bake --set foo*.no-cache # bypass caching only for targets starting with "foo" +``` + +Complete list of overridable fields: + +* `args` +* `cache-from` +* `cache-to` +* `context` +* `dockerfile` +* `labels` +* `no-cache` +* `output` +* `platform` +* `pull` +* `secrets` +* `ssh` +* `tags` +* `target` + +## Using variables in variables across files + +When multiple files are specified, one file can use variables defined in +another file. + +```hcl +# docker-bake1.hcl +variable "FOO" { + default = upper("${BASE}def") +} + +variable "BAR" { + default = "-${FOO}-" +} + +target "app" { + args = { + v1 = "pre-${BAR}" + } +} +``` + +```hcl +# docker-bake2.hcl +variable "BASE" { + default = "abc" +} + +target "app" { + args = { + v2 = "${FOO}-post" + } +} +``` + +```console +$ docker buildx bake -f docker-bake1.hcl -f docker-bake2.hcl --print app +``` +```json +{ + "group": { + "default": { + "targets": [ + "app" + ] + } + }, + "target": { + "app": { + "context": ".", + "dockerfile": "Dockerfile", + "args": { + "v1": "pre--ABCDEF-", + "v2": "ABCDEF-post" + } + } + } +} +``` diff --git a/build/customize/bake/file-definition.md b/build/customize/bake/file-definition.md index 2ee188cedb..5ac7776931 100644 --- a/build/customize/bake/file-definition.md +++ b/build/customize/bake/file-definition.md @@ -3,7 +3,443 @@ title: "Bake file definition" keywords: build, buildx, bake, buildkit, hcl, json, compose redirect_from: - /build/bake/file-definition/ -fetch_remote: - line_start: 2 - line_end: -1 --- + +`buildx bake` supports HCL, JSON and Compose file format for defining build +[groups](#group), [targets](#target) as well as [variables](#variable) and +[functions](#functions). It looks for build definition files in the current +directory in the following order: + +* `docker-compose.yml` +* `docker-compose.yaml` +* `docker-bake.json` +* `docker-bake.override.json` +* `docker-bake.hcl` +* `docker-bake.override.hcl` + +## Specification + +Inside a bake file you can declare group, target and variable blocks to define +project specific reusable build flows. + +### Target + +A target reflects a single docker build invocation with the same options that +you would specify for `docker build`: + +```hcl +# docker-bake.hcl +target "webapp-dev" { + dockerfile = "Dockerfile.webapp" + tags = ["docker.io/username/webapp:latest"] +} +``` +```console +$ docker buildx bake webapp-dev +``` + +> **Note** +> +> In the case of compose files, each service corresponds to a target. +> If compose service name contains a dot it will be replaced with an underscore. + +Complete list of valid target fields available for [HCL](#hcl-definition) and +[JSON](#json-definition) definitions: + +| Name | Type | Description | +|---------------------|--------|------------------------------------------------------------------------------------------------------------------------------------| +| `inherits` | List | [Inherit build options](#merging-and-inheritance) from other targets | +| `args` | Map | Set build-time variables (same as [`--build-arg` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `cache-from` | List | External cache sources (same as [`--cache-from` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `cache-to` | List | Cache export destinations (same as [`--cache-to` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `context` | String | Set of files located in the specified path or URL | +| `contexts` | Map | Additional build contexts (same as [`--build-context` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `dockerfile` | String | Name of the Dockerfile (same as [`--file` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `dockerfile-inline` | String | Inline Dockerfile content | +| `labels` | Map | Set metadata for an image (same as [`--label` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `no-cache` | Bool | Do not use cache when building the image (same as [`--no-cache` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `no-cache-filter` | List | Do not cache specified stages (same as [`--no-cache-filter` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `output` | List | Output destination (same as [`--output` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `platforms` | List | Set target platforms for build (same as [`--platform` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `pull` | Bool | Always attempt to pull all referenced images (same as [`--pull` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `secret` | List | Secret to expose to the build (same as [`--secret` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `ssh` | List | SSH agent socket or keys to expose to the build (same as [`--ssh` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `tags` | List | Name and optionally a tag in the format `name:tag` (same as [`--tag` flag](../../../engine/reference/commandline/buildx_build.md)) | +| `target` | String | Set the target build stage to build (same as [`--target` flag](../../../engine/reference/commandline/buildx_build.md)) | + +### Group + +A group is a grouping of targets: + +```hcl +# docker-bake.hcl +group "build" { + targets = ["db", "webapp-dev"] +} + +target "webapp-dev" { + dockerfile = "Dockerfile.webapp" + tags = ["docker.io/username/webapp:latest"] +} + +target "db" { + dockerfile = "Dockerfile.db" + tags = ["docker.io/username/db"] +} +``` +```console +$ docker buildx bake build +``` + +### Variable + +Similar to how Terraform provides a way to [define variables](https://www.terraform.io/docs/configuration/variables.html#declaring-an-input-variable){:target="_blank" rel="noopener" class="_"}, +the HCL file format also supports variable block definitions. These can be used +to define variables with values provided by the current environment, or a +default value when unset: + +```hcl +# docker-bake.hcl +variable "TAG" { + default = "latest" +} + +target "webapp-dev" { + dockerfile = "Dockerfile.webapp" + tags = ["docker.io/username/webapp:${TAG}"] +} +``` +```console +$ docker buildx bake webapp-dev # will use the default value "latest" +$ TAG=dev docker buildx bake webapp-dev # will use the TAG environment variable value +``` + +> **Tip** +> +> See also the [Configuring builds](configuring-build.md) page for advanced usage. + +### Functions + +A [set of generally useful functions](https://github.com/docker/buildx/blob/master/bake/hclparser/stdlib.go){:target="_blank" rel="noopener" class="_"} +provided by [go-cty](https://github.com/zclconf/go-cty/tree/main/cty/function/stdlib){:target="_blank" rel="noopener" class="_"} +are available for use in HCL files: + +```hcl +# docker-bake.hcl +target "webapp-dev" { + dockerfile = "Dockerfile.webapp" + tags = ["docker.io/username/webapp:latest"] + args = { + buildno = "${add(123, 1)}" + } +} +``` + +In addition, [user defined functions](https://github.com/hashicorp/hcl/tree/main/ext/userfunc){:target="_blank" rel="noopener" class="_"} +are also supported: + +```hcl +# docker-bake.hcl +function "increment" { + params = [number] + result = number + 1 +} + +target "webapp-dev" { + dockerfile = "Dockerfile.webapp" + tags = ["docker.io/username/webapp:latest"] + args = { + buildno = "${increment(123)}" + } +} +``` + +> **Note** +> +> See [User defined HCL functions](hcl-funcs.md) page for more details. + +## Built-in variables + +* `BAKE_CMD_CONTEXT` can be used to access the main `context` for bake command + from a bake file that has been [imported remotely](file-definition.md#remote-definition). +* `BAKE_LOCAL_PLATFORM` returns the current platform's default platform + specification (e.g. `linux/amd64`). + +## Merging and inheritance + +Multiple files can include the same target and final build options will be +determined by merging them together: + +```hcl +# docker-bake.hcl +target "webapp-dev" { + dockerfile = "Dockerfile.webapp" + tags = ["docker.io/username/webapp:latest"] +} +``` +```hcl +# docker-bake2.hcl +target "webapp-dev" { + tags = ["docker.io/username/webapp:dev"] +} +``` +```console +$ docker buildx bake -f docker-bake.hcl -f docker-bake2.hcl webapp-dev +``` + +A group can specify its list of targets with the `targets` option. A target can +inherit build options by setting the `inherits` option to the list of targets or +groups to inherit from: + +```hcl +# docker-bake.hcl +target "webapp-dev" { + dockerfile = "Dockerfile.webapp" + tags = ["docker.io/username/webapp:${TAG}"] +} + +target "webapp-release" { + inherits = ["webapp-dev"] + platforms = ["linux/amd64", "linux/arm64"] +} +``` + +## `default` target/group + +When you invoke `bake` you specify what targets/groups you want to build. If no +arguments is specified, the group/target named `default` will be built: + +```hcl +# docker-bake.hcl +target "default" { + dockerfile = "Dockerfile.webapp" + tags = ["docker.io/username/webapp:latest"] +} +``` +```console +$ docker buildx bake +``` + +## Definitions + +### HCL definition + +HCL definition file is recommended as its experience is more aligned with buildx UX +and also allows better code reuse, different target groups and extended features. + +```hcl +# docker-bake.hcl +variable "TAG" { + default = "latest" +} + +group "default" { + targets = ["db", "webapp-dev"] +} + +target "webapp-dev" { + dockerfile = "Dockerfile.webapp" + tags = ["docker.io/username/webapp:${TAG}"] +} + +target "webapp-release" { + inherits = ["webapp-dev"] + platforms = ["linux/amd64", "linux/arm64"] +} + +target "db" { + dockerfile = "Dockerfile.db" + tags = ["docker.io/username/db"] +} +``` + +### JSON definition + +```json +{ + "variable": { + "TAG": { + "default": "latest" + } + }, + "group": { + "default": { + "targets": [ + "db", + "webapp-dev" + ] + } + }, + "target": { + "webapp-dev": { + "dockerfile": "Dockerfile.webapp", + "tags": [ + "docker.io/username/webapp:${TAG}" + ] + }, + "webapp-release": { + "inherits": [ + "webapp-dev" + ], + "platforms": [ + "linux/amd64", + "linux/arm64" + ] + }, + "db": { + "dockerfile": "Dockerfile.db", + "tags": [ + "docker.io/username/db" + ] + } + } +} +``` + +### Compose file + +```yaml +# docker-compose.yml +services: + webapp: + image: docker.io/username/webapp:latest + build: + dockerfile: Dockerfile.webapp + + db: + image: docker.io/username/db + build: + dockerfile: Dockerfile.db +``` + +> **Note** +> +> See [Building from Compose file](compose-file.md) page for more details. + +## Remote definition + +You can also build bake files directly from a remote Git repository or HTTPS URL: + +```console +$ docker buildx bake "https://github.com/docker/cli.git#v20.10.11" --print +#1 [internal] load git source https://github.com/docker/cli.git#v20.10.11 +#1 0.745 e8f1871b077b64bcb4a13334b7146492773769f7 refs/tags/v20.10.11 +#1 2.022 From https://github.com/docker/cli +#1 2.022 * [new tag] v20.10.11 -> v20.10.11 +#1 DONE 2.9s +``` +```json +{ + "group": { + "default": { + "targets": [ + "binary" + ] + } + }, + "target": { + "binary": { + "context": "https://github.com/docker/cli.git#v20.10.11", + "dockerfile": "Dockerfile", + "args": { + "BASE_VARIANT": "alpine", + "GO_STRIP": "", + "VERSION": "" + }, + "target": "binary", + "platforms": [ + "local" + ], + "output": [ + "build" + ] + } + } +} +``` + +As you can see the context is fixed to `https://github.com/docker/cli.git` even if +[no context is actually defined](https://github.com/docker/cli/blob/2776a6d694f988c0c1df61cad4bfac0f54e481c8/docker-bake.hcl#L17-L26){:target="_blank" rel="noopener" class="_"} +in the definition. + +If you want to access the main context for bake command from a bake file +that has been imported remotely, you can use the [`BAKE_CMD_CONTEXT` built-in var](#built-in-variables). + +```console +$ cat https://raw.githubusercontent.com/tonistiigi/buildx/remote-test/docker-bake.hcl +``` +```hcl +target "default" { + context = BAKE_CMD_CONTEXT + dockerfile-inline = < [4/4] RUN ls -l && stop: +#8 0.101 total 0 +#8 0.102 -rw-r--r-- 1 root root 0 Jul 27 18:47 bar +#8 0.102 -rw-r--r-- 1 root root 0 Jul 27 18:47 foo +#8 0.102 /bin/sh: stop: not found +``` + +```console +$ docker buildx bake "https://github.com/tonistiigi/buildx.git#remote-test" "https://github.com/docker/cli.git#v20.10.11" --print +#1 [internal] load git source https://github.com/tonistiigi/buildx.git#remote-test +#1 0.429 577303add004dd7efeb13434d69ea030d35f7888 refs/heads/remote-test +#1 CACHED +``` +```json +{ + "target": { + "default": { + "context": "https://github.com/docker/cli.git#v20.10.11", + "dockerfile": "Dockerfile", + "dockerfile-inline": "FROM alpine\nWORKDIR /src\nCOPY . .\nRUN ls -l \u0026\u0026 stop\n" + } + } +} +``` + +```console +$ docker buildx bake "https://github.com/tonistiigi/buildx.git#remote-test" "https://github.com/docker/cli.git#v20.10.11" +``` +```text +... + > [4/4] RUN ls -l && stop: +#8 0.136 drwxrwxrwx 5 root root 4096 Jul 27 18:31 kubernetes +#8 0.136 drwxrwxrwx 3 root root 4096 Jul 27 18:31 man +#8 0.136 drwxrwxrwx 2 root root 4096 Jul 27 18:31 opts +#8 0.136 -rw-rw-rw- 1 root root 1893 Jul 27 18:31 poule.yml +#8 0.136 drwxrwxrwx 7 root root 4096 Jul 27 18:31 scripts +#8 0.136 drwxrwxrwx 3 root root 4096 Jul 27 18:31 service +#8 0.136 drwxrwxrwx 2 root root 4096 Jul 27 18:31 templates +#8 0.136 drwxrwxrwx 10 root root 4096 Jul 27 18:31 vendor +#8 0.136 -rwxrwxrwx 1 root root 9620 Jul 27 18:31 vendor.conf +#8 0.136 /bin/sh: stop: not found +``` diff --git a/build/customize/bake/hcl-funcs.md b/build/customize/bake/hcl-funcs.md index 3773921185..be49bdf5e0 100644 --- a/build/customize/bake/hcl-funcs.md +++ b/build/customize/bake/hcl-funcs.md @@ -3,7 +3,330 @@ title: "User defined HCL functions" keywords: build, buildx, bake, buildkit, hcl redirect_from: - /build/bake/hcl-funcs/ -fetch_remote: - line_start: 2 - line_end: -1 --- + +## Using interpolation to tag an image with the git sha + +As shown in the [File definition](file-definition.md#variable) page, `bake` +supports variable blocks which are assigned to matching environment variables +or default values: + +```hcl +# docker-bake.hcl +variable "TAG" { + default = "latest" +} + +group "default" { + targets = ["webapp"] +} + +target "webapp" { + tags = ["docker.io/username/webapp:${TAG}"] +} +``` + +alternatively, in json format: + +```json +{ + "variable": { + "TAG": { + "default": "latest" + } + }, + "group": { + "default": { + "targets": ["webapp"] + } + }, + "target": { + "webapp": { + "tags": ["docker.io/username/webapp:${TAG}"] + } + } +} +``` + +```console +$ docker buildx bake --print webapp +``` +```json +{ + "group": { + "default": { + "targets": [ + "webapp" + ] + } + }, + "target": { + "webapp": { + "context": ".", + "dockerfile": "Dockerfile", + "tags": [ + "docker.io/username/webapp:latest" + ] + } + } +} +``` + +```console +$ TAG=$(git rev-parse --short HEAD) docker buildx bake --print webapp +``` +```json +{ + "group": { + "default": { + "targets": [ + "webapp" + ] + } + }, + "target": { + "webapp": { + "context": ".", + "dockerfile": "Dockerfile", + "tags": [ + "docker.io/username/webapp:985e9e9" + ] + } + } +} +``` + +## Using the `add` function + +You can use [`go-cty` stdlib functions](https://github.com/zclconf/go-cty/tree/main/cty/function/stdlib){:target="_blank" rel="noopener" class="_"}. +Here we are using the `add` function. + +```hcl +# docker-bake.hcl +variable "TAG" { + default = "latest" +} + +group "default" { + targets = ["webapp"] +} + +target "webapp" { + args = { + buildno = "${add(123, 1)}" + } +} +``` + +```console +$ docker buildx bake --print webapp +``` +```json +{ + "group": { + "default": { + "targets": [ + "webapp" + ] + } + }, + "target": { + "webapp": { + "context": ".", + "dockerfile": "Dockerfile", + "args": { + "buildno": "124" + } + } + } +} +``` + +## Defining an `increment` function + +It also supports [user defined functions](https://github.com/hashicorp/hcl/tree/main/ext/userfunc){:target="_blank" rel="noopener" class="_"}. +The following example defines a simple an `increment` function. + +```hcl +# docker-bake.hcl +function "increment" { + params = [number] + result = number + 1 +} + +group "default" { + targets = ["webapp"] +} + +target "webapp" { + args = { + buildno = "${increment(123)}" + } +} +``` + +```console +$ docker buildx bake --print webapp +``` +```json +{ + "group": { + "default": { + "targets": [ + "webapp" + ] + } + }, + "target": { + "webapp": { + "context": ".", + "dockerfile": "Dockerfile", + "args": { + "buildno": "124" + } + } + } +} +``` + +## Only adding tags if a variable is not empty using an `notequal` + +Here we are using the conditional `notequal` function which is just for +symmetry with the `equal` one. + +```hcl +# docker-bake.hcl +variable "TAG" {default="" } + +group "default" { + targets = [ + "webapp", + ] +} + +target "webapp" { + context="." + dockerfile="Dockerfile" + tags = [ + "my-image:latest", + notequal("",TAG) ? "my-image:${TAG}": "", + ] +} +``` + +```console +$ docker buildx bake --print webapp +``` +```json +{ + "group": { + "default": { + "targets": [ + "webapp" + ] + } + }, + "target": { + "webapp": { + "context": ".", + "dockerfile": "Dockerfile", + "tags": [ + "my-image:latest" + ] + } + } +} +``` + +## Using variables in functions + +You can refer variables to other variables like the target blocks can. Stdlib +functions can also be called but user functions can't at the moment. + +```hcl +# docker-bake.hcl +variable "REPO" { + default = "user/repo" +} + +function "tag" { + params = [tag] + result = ["${REPO}:${tag}"] +} + +target "webapp" { + tags = tag("v1") +} +``` + +```console +$ docker buildx bake --print webapp +``` +```json +{ + "group": { + "default": { + "targets": [ + "webapp" + ] + } + }, + "target": { + "webapp": { + "context": ".", + "dockerfile": "Dockerfile", + "tags": [ + "user/repo:v1" + ] + } + } +} +``` + +## Using typed variables + +Non-string variables are also accepted. The value passed with env is parsed +into suitable type first. + +```hcl +# docker-bake.hcl +variable "FOO" { + default = 3 +} + +variable "IS_FOO" { + default = true +} + +target "app" { + args = { + v1 = FOO > 5 ? "higher" : "lower" + v2 = IS_FOO ? "yes" : "no" + } +} +``` + +```console +$ docker buildx bake --print app +``` +```json +{ + "group": { + "default": { + "targets": [ + "app" + ] + } + }, + "target": { + "app": { + "context": ".", + "dockerfile": "Dockerfile", + "args": { + "v1": "lower", + "v2": "yes" + } + } + } +} +``` diff --git a/build/customize/bake/index.md b/build/customize/bake/index.md index d5dbc030de..647bdb6273 100644 --- a/build/customize/bake/index.md +++ b/build/customize/bake/index.md @@ -3,7 +3,39 @@ title: High-level builds with Bake keywords: build, buildx, bake, buildkit, hcl, json, compose redirect_from: - /build/bake/ -fetch_remote: - line_start: 2 - line_end: -1 --- + +> This command is experimental. +> +> The design of bake is in early stages, and we are looking for [feedback from users](https://github.com/docker/buildx/issues){:target="_blank" rel="noopener" class="_"}. +{: .experimental } + +Buildx also aims to provide support for high-level build concepts that go beyond +invoking a single build command. We want to support building all the images in +your application together and let the users define project specific reusable +build flows that can then be easily invoked by anyone. + +[BuildKit](https://github.com/moby/buildkit){:target="_blank" rel="noopener" class="_"} +efficiently handles multiple concurrent build requests and de-duplicating work. +The build commands can be combined with general-purpose command runners +(for example, `make`). However, these tools generally invoke builds in sequence +and therefore cannot leverage the full potential of BuildKit parallelization, +or combine BuildKit's output for the user. For this use case, we have added a +command called [`docker buildx bake`](../../../engine/reference/commandline/buildx_bake.md). + +The `bake` command supports building images from HCL, JSON and Compose files. +This is similar to [`docker compose build`](../../../compose/compose-file/build.md), +but allowing all the services to be built concurrently as part of a single +request. If multiple files are specified they are all read and configurations are +combined. + +We recommend using HCL files as its experience is more aligned with buildx UX +and also allows better code reuse, different target groups and extended features. + +## Next steps + +* [File definition](file-definition.md) +* [Configuring builds](configuring-build.md) +* [User defined HCL functions](hcl-funcs.md) +* [Defining additional build contexts and linking targets](build-contexts.md) +* [Building from Compose file](compose-file.md)