How to use docker buildx bake command to build multiple targets

DockerDockerBeginner
Practice Now

Introduction

In this lab, you will learn how to effectively use the docker buildx bake command to manage and build multiple Docker image targets from a single configuration file. We will start by creating a docker-bake.hcl file that defines different build targets with varying configurations.

Through hands-on steps, you will practice building specific targets defined in the bake file, listing the available targets, overriding target configurations using command-line flags, and previewing the build configuration without actually performing the build. This lab will equip you with the skills to streamline your Docker image building workflows for complex projects.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker(("Docker")) -.-> docker/DockerfileGroup(["Dockerfile"]) docker/ImageOperationsGroup -.-> docker/images("List Images") docker/DockerfileGroup -.-> docker/build("Build Image from Dockerfile") subgraph Lab Skills docker/images -.-> lab-555044{{"How to use docker buildx bake command to build multiple targets"}} docker/build -.-> lab-555044{{"How to use docker buildx bake command to build multiple targets"}} end

Create a simple docker-bake.hcl file with multiple targets

In this step, we will create a basic docker-bake.hcl file. This file uses the HCL (HashiCorp Configuration Language) format and allows you to define multiple build targets for your Docker images. This is particularly useful when you have different build configurations or want to build multiple related images from a single source.

First, navigate to the ~/project directory, which is your working directory for this lab.

cd ~/project

Now, let's create a new file named docker-bake.hcl using the nano editor.

nano docker-bake.hcl

Inside the nano editor, paste the following content. This file defines two build targets: my-app-dev and my-app-prod. Each target specifies the Dockerfile to use (Dockerfile), the build context (.), and the tags for the resulting image.

target "my-app-dev" {
  dockerfile = "Dockerfile"
  context = "."
  tags = ["my-app:dev"]
}

target "my-app-prod" {
  dockerfile = "Dockerfile"
  context = "."
  tags = ["my-app:prod"]
  args = {
    BUILD_ENV = "production"
  }
}

In this file:

  • target "my-app-dev" defines a target named my-app-dev.
  • dockerfile = "Dockerfile" specifies that the build should use a file named Dockerfile in the context.
  • context = "." sets the build context to the current directory.
  • tags = ["my-app:dev"] assigns the tag my-app:dev to the resulting image.
  • target "my-app-prod" defines another target named my-app-prod.
  • It also uses Dockerfile and the current directory as context.
  • tags = ["my-app:prod"] assigns the tag my-app:prod to this image.
  • args = { BUILD_ENV = "production" } passes a build argument BUILD_ENV with the value production to the Dockerfile during the build of this target.

Save the file by pressing Ctrl + S and exit nano by pressing Ctrl + X.

Next, we need a simple Dockerfile for our bake file to reference. Create a file named Dockerfile in the same directory.

nano Dockerfile

Paste the following content into the Dockerfile:

FROM alpine:latest

ARG BUILD_ENV=development

RUN echo "Building for environment: $BUILD_ENV"

CMD ["echo", "Hello from $BUILD_ENV environment!"]

This Dockerfile uses the alpine:latest base image. It defines a build argument BUILD_ENV with a default value of development. The RUN instruction prints the build environment during the build process, and the CMD instruction sets the default command to run when a container is started from this image.

Save the Dockerfile and exit nano.

You have now successfully created a docker-bake.hcl file with two targets and a simple Dockerfile to be used with it.

Build a specific target using docker buildx bake

In the previous step, we created a docker-bake.hcl file with two build targets: my-app-dev and my-app-prod. Now, we will use the docker buildx bake command to build a specific target defined in this file.

The docker buildx bake command allows you to build images based on the configurations defined in a bake file. By specifying the target name after the command, you instruct Buildx to build only that particular target.

Let's build the my-app-dev target. Make sure you are in the ~/project directory.

cd ~/project

Now, execute the following command:

docker buildx bake my-app-dev

This command will read the docker-bake.hcl file in the current directory and build the target named my-app-dev. You should see output indicating the build process, including the steps defined in the Dockerfile.

[+] Building 0.0s (0/0)
... (build output) ...

After the build completes, you can verify that the image my-app:dev has been created by listing your local Docker images.

docker images

You should see my-app with the tag dev in the list of images.

Now, let's build the my-app-prod target. This target includes a build argument BUILD_ENV set to production.

docker buildx bake my-app-prod

Observe the output. You should see the line Building for environment: production during the build process, which confirms that the build argument was passed correctly.

[+] Building 0.0s (0/0)
... (build output showing "Building for environment: production") ...

After this build finishes, list your images again.

docker images

You should now see both my-app:dev and my-app:prod in your list of images.

By using docker buildx bake followed by the target name, you can selectively build different configurations defined in your bake file.

List available targets in the bake file

In the previous steps, we created a docker-bake.hcl file and built specific targets from it. Sometimes, you might want to see all the available targets defined in a bake file without actually building them. The docker buildx bake command provides a way to do this.

To list the available targets, you can simply run the docker buildx bake command without specifying any target names. By default, it will read the docker-bake.hcl file in the current directory and display the names of all defined targets.

Make sure you are in the ~/project directory where your docker-bake.hcl file is located.

cd ~/project

Now, execute the following command:

docker buildx bake

You should see output similar to this, listing the targets defined in your docker-bake.hcl file:

my-app-dev
my-app-prod

This output shows the names of the two targets we defined in the docker-bake.hcl file: my-app-dev and my-app-prod. This is a quick way to get an overview of the build configurations available in a bake file.

This command is useful for understanding the structure of a bake file and identifying the targets you can build.

Override target configuration using the --set flag

In this step, we will learn how to override the configuration of a specific target defined in the docker-bake.hcl file using the --set flag with the docker buildx bake command. This is useful when you need to make minor adjustments to a target's configuration without modifying the bake file itself.

The --set flag allows you to override specific attributes of a target. The syntax is target_name.attribute=value.

Let's say we want to build the my-app-dev target but with a different tag, for example, my-app:staging. We can achieve this using the --set flag.

Make sure you are in the ~/project directory.

cd ~/project

Now, execute the following command:

docker buildx bake my-app-dev --set my-app-dev.tags=my-app:staging

In this command:

  • my-app-dev is the name of the target we are building.
  • --set my-app-dev.tags=my-app:staging overrides the tags attribute of the my-app-dev target, setting its value to my-app:staging.

You will see the build process output.

[+] Building 0.0s (0/0)
... (build output) ...

After the build completes, list your local Docker images to verify that the image with the new tag has been created.

docker images

You should now see my-app with the tag staging in the list, in addition to the dev and prod tags from previous steps.

You can also override other attributes, such as build arguments. Let's build the my-app-prod target but override the BUILD_ENV argument to qa.

docker buildx bake my-app-prod --set my-app-prod.args.BUILD_ENV=qa

Observe the build output. You should see Building for environment: qa, indicating that the build argument was successfully overridden.

[+] Building 0.0s (0/0)
... (build output showing "Building for environment: qa") ...

The --set flag provides a flexible way to customize your builds directly from the command line without altering your bake file.

Print the resulting configuration without building

In this final step, we will explore how to view the final configuration that docker buildx bake will use for a specific target, including any overrides applied with the --set flag, without actually triggering a build. This is useful for debugging your bake files and understanding the effective configuration before building.

The --print flag with docker buildx bake allows you to output the resolved configuration in JSON format.

Make sure you are in the ~/project directory.

cd ~/project

Let's print the configuration for the my-app-dev target.

docker buildx bake my-app-dev --print

This command will output a JSON representation of the my-app-dev target's configuration as derived from the docker-bake.hcl file.

{
  "target": {
    "my-app-dev": {
      "dockerfile": "Dockerfile",
      "context": ".",
      "tags": ["my-app:dev"]
    }
  }
}

Now, let's see how the --set flag affects the printed configuration. We will print the configuration for my-app-dev while overriding the tag to my-app:testing.

docker buildx bake my-app-dev --set my-app-dev.tags=my-app:testing --print

Observe the output. The tags attribute in the JSON output should now reflect the overridden value.

{
  "target": {
    "my-app-dev": {
      "dockerfile": "Dockerfile",
      "context": ".",
      "tags": ["my-app:testing"]
    }
  }
}

Similarly, you can print the configuration for the my-app-prod target and override its build argument.

docker buildx bake my-app-prod --set my-app-prod.args.BUILD_ENV=staging --print

The JSON output for the my-app-prod target will show the args with the overridden BUILD_ENV value.

{
  "target": {
    "my-app-prod": {
      "dockerfile": "Dockerfile",
      "context": ".",
      "tags": ["my-app:prod"],
      "args": {
        "BUILD_ENV": "staging"
      }
    }
  }
}

The --print flag is a valuable tool for verifying your bake file configurations and understanding how overrides are applied before initiating potentially time-consuming builds.

Summary

In this lab, we learned how to leverage the docker buildx bake command to manage and build multiple Docker image targets defined in a single docker-bake.hcl file. We started by creating a basic docker-bake.hcl file with distinct targets, each specifying its Dockerfile, context, tags, and build arguments.

We then explored how to build a specific target from the bake file using docker buildx bake <target_name>, list all available targets within the file, override target configurations on the fly using the --set flag, and preview the resulting build configuration without actually performing the build using the --print flag. These steps demonstrate the flexibility and power of docker buildx bake for streamlining complex multi-image build workflows.