|
| 1 | +--- |
| 2 | +title: Docker Bake |
| 3 | +ogTitle: How to build multiple Docker images in parallel with Depot bake |
| 4 | +description: Learn how to use depot bake to build multiple container images concurrently from HCL, JSON, or Docker Compose files |
| 5 | +--- |
| 6 | + |
| 7 | +Building multiple Docker images that share common dependencies? Need to build all your services at once? `depot bake` lets you build multiple images in parallel from a single file, dramatically speeding up your builds while taking advantage of shared work between images. |
| 8 | + |
| 9 | +## Why use bake? |
| 10 | + |
| 11 | +Traditional approaches to building multiple images often involve sequential builds using tools like `make` or shell scripts. This means waiting for each image to complete before starting the next one, and rebuilding shared dependencies multiple times. |
| 12 | + |
| 13 | +With `depot bake`, you can: |
| 14 | + |
| 15 | +- Build all images in parallel on dedicated BuildKit builders |
| 16 | +- Automatically deduplicate shared work across images |
| 17 | +- Define all your builds in a single HCL, JSON, or Docker Compose file |
| 18 | +- Get native Intel and Arm builds without emulation |
| 19 | +- Leverage persistent caching across all your builds |
| 20 | + |
| 21 | +## How to use depot bake |
| 22 | + |
| 23 | +### Basic usage |
| 24 | + |
| 25 | +By default, `depot bake` looks for these files in your project root: |
| 26 | + |
| 27 | +- `compose.yaml`, `compose.yml`, `docker-compose.yml`, `docker-compose.yaml` |
| 28 | +- `docker-bake.json`, `docker-bake.override.json` |
| 29 | +- `docker-bake.hcl`, `docker-bake.override.hcl` |
| 30 | + |
| 31 | +Run bake with no arguments to build the default group or all services: |
| 32 | + |
| 33 | +```shell |
| 34 | +depot bake |
| 35 | +``` |
| 36 | + |
| 37 | +### Specifying a bake file |
| 38 | + |
| 39 | +Use the `-f` flag to specify a custom bake file: |
| 40 | + |
| 41 | +```shell |
| 42 | +depot bake -f my-bake-file.hcl |
| 43 | +``` |
| 44 | + |
| 45 | +### Building specific targets |
| 46 | + |
| 47 | +Build only specific targets instead of all: |
| 48 | + |
| 49 | +```shell |
| 50 | +depot bake app db |
| 51 | +``` |
| 52 | + |
| 53 | +## HCL bake file format |
| 54 | + |
| 55 | +HCL is the recommended format for bake files as it provides the most features and flexibility. |
| 56 | + |
| 57 | +### Basic example |
| 58 | + |
| 59 | +```hcl |
| 60 | +group "default" { |
| 61 | + targets = ["app", "db", "cron"] |
| 62 | +} |
| 63 | +
|
| 64 | +target "app" { |
| 65 | + dockerfile = "Dockerfile.app" |
| 66 | + platforms = ["linux/amd64", "linux/arm64"] |
| 67 | + tags = ["myrepo/app:latest"] |
| 68 | +} |
| 69 | +
|
| 70 | +target "db" { |
| 71 | + dockerfile = "Dockerfile.db" |
| 72 | + platforms = ["linux/amd64", "linux/arm64"] |
| 73 | + tags = ["myrepo/db:latest"] |
| 74 | +} |
| 75 | +
|
| 76 | +target "cron" { |
| 77 | + dockerfile = "Dockerfile.cron" |
| 78 | + platforms = ["linux/amd64", "linux/arm64"] |
| 79 | + tags = ["myrepo/cron:latest"] |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +You can think of each `target` as a Docker build command, where you specify the Dockerfile, platforms, and tags for the image. These targets can be grouped together in a `group` to build them all at once. |
| 84 | + |
| 85 | +Our optimized instances of BuildKit will build these images in parallel, automatically deduplicating work across targets. |
| 86 | + |
| 87 | +### Using variables |
| 88 | + |
| 89 | +Make your bake files more flexible with variables: |
| 90 | + |
| 91 | +```hcl |
| 92 | +variable "TAG" { |
| 93 | + default = "latest" |
| 94 | +} |
| 95 | +
|
| 96 | +variable "REGISTRY" { |
| 97 | + default = "myrepo" |
| 98 | +} |
| 99 | +
|
| 100 | +target "app" { |
| 101 | + dockerfile = "Dockerfile.app" |
| 102 | + platforms = ["linux/amd64", "linux/arm64"] |
| 103 | + tags = ["${REGISTRY}/app:${TAG}"] |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +Override variables from the command line: |
| 108 | + |
| 109 | +```shell |
| 110 | +TAG=v1.0.0 REGISTRY=mycompany depot bake |
| 111 | +``` |
| 112 | + |
| 113 | +### Sharing base images |
| 114 | + |
| 115 | +Use `contexts` to specify dependencies between targets in a bake file. A common use of this is to highlight that targets share a base image, so you can deduplicate work by only building that base image once: |
| 116 | + |
| 117 | +```hcl |
| 118 | +target "base" { |
| 119 | + dockerfile = "Dockerfile.base" |
| 120 | + platforms = ["linux/amd64", "linux/arm64"] |
| 121 | +} |
| 122 | +
|
| 123 | +target "app" { |
| 124 | + contexts = { |
| 125 | + base = "target:base" |
| 126 | + } |
| 127 | + dockerfile = "Dockerfile.app" |
| 128 | + platforms = ["linux/amd64", "linux/arm64"] |
| 129 | + tags = ["myrepo/app:latest"] |
| 130 | +} |
| 131 | +
|
| 132 | +target "worker" { |
| 133 | + contexts = { |
| 134 | + base = "target:base" |
| 135 | + } |
| 136 | + dockerfile = "Dockerfile.worker" |
| 137 | + platforms = ["linux/amd64", "linux/arm64"] |
| 138 | + tags = ["myrepo/worker:latest"] |
| 139 | +} |
| 140 | +``` |
| 141 | + |
| 142 | +In your Dockerfiles, reference the base context: |
| 143 | + |
| 144 | +```dockerfile |
| 145 | +# Dockerfile.app |
| 146 | +FROM base |
| 147 | +# ... rest of your app Dockerfile |
| 148 | +``` |
| 149 | + |
| 150 | +### Matrix builds |
| 151 | + |
| 152 | +You can use the matrix key to parameterize a single target to build images for different inputs. This can be helpful if you have a lot of similarities between targets in your bake file. |
| 153 | + |
| 154 | +```hcl |
| 155 | +target "service" { |
| 156 | + name = "service-${item}" |
| 157 | + matrix = { |
| 158 | + item = ["frontend", "backend", "api"] |
| 159 | + } |
| 160 | + dockerfile = "Dockerfile.${item}" |
| 161 | + platforms = ["linux/amd64", "linux/arm64"] |
| 162 | + tags = ["myrepo/${item}:latest"] |
| 163 | +} |
| 164 | +``` |
| 165 | + |
| 166 | +**Note: The name property is required when using the matrix property to create the unique image build for each value in the matrix.** |
| 167 | + |
| 168 | +## Docker Compose bake format |
| 169 | + |
| 170 | +You can use your existing Docker Compose files as a bake file. There are limitations compared to HCL, like not supporting `inherits` or variable blocks. But it's a great way to build all of your services in parallel without needing to rewrite your existing Compose files. |
| 171 | + |
| 172 | +```yaml |
| 173 | +services: |
| 174 | + app: |
| 175 | + build: |
| 176 | + dockerfile: Dockerfile.app |
| 177 | + platforms: |
| 178 | + - linux/amd64 |
| 179 | + - linux/arm64 |
| 180 | + image: myrepo/app:latest |
| 181 | + |
| 182 | + db: |
| 183 | + build: |
| 184 | + dockerfile: Dockerfile.db |
| 185 | + platforms: |
| 186 | + - linux/amd64 |
| 187 | + - linux/arm64 |
| 188 | + image: myrepo/db:latest |
| 189 | + |
| 190 | + worker: |
| 191 | + build: |
| 192 | + dockerfile: Dockerfile.worker |
| 193 | + platforms: |
| 194 | + - linux/amd64 |
| 195 | + - linux/arm64 |
| 196 | + image: myrepo/worker:latest |
| 197 | +``` |
| 198 | +
|
| 199 | +Build all services defined in the Docker Compose file with: |
| 200 | +
|
| 201 | +```shell |
| 202 | +depot bake -f docker-compose.yml |
| 203 | +``` |
| 204 | + |
| 205 | +## Advanced features |
| 206 | + |
| 207 | +### Using multiple Depot projects in a bake file |
| 208 | + |
| 209 | +In some cases you may want to shard your container builds out across different Depot projects so you can have the full BuildKit host dedicated to the build. For compose, you can specify different Depot projects per service. |
| 210 | + |
| 211 | +```yaml |
| 212 | +services: |
| 213 | + frontend: |
| 214 | + build: |
| 215 | + dockerfile: ./Dockerfile.frontend |
| 216 | + x-depot: |
| 217 | + project-id: project-id-1 |
| 218 | + backend: |
| 219 | + build: |
| 220 | + dockerfile: ./Dockerfile.backend |
| 221 | + x-depot: |
| 222 | + project-id: project-id-2 |
| 223 | +``` |
| 224 | +
|
| 225 | +You can also specify the project ID in HCL for each `target`: |
| 226 | + |
| 227 | +```hcl |
| 228 | +target "app" { |
| 229 | + dockerfile = "Dockerfile.app" |
| 230 | + platforms = ["linux/amd64", "linux/arm64"] |
| 231 | + tags = ["myrepo/app:latest"] |
| 232 | + project_id = "project-id-1" |
| 233 | +} |
| 234 | +
|
| 235 | +target "db" { |
| 236 | + dockerfile = "Dockerfile.db" |
| 237 | + platforms = ["linux/amd64", "linux/arm64"] |
| 238 | + tags = ["myrepo/db:latest"] |
| 239 | + project_id = "project-id-2" |
| 240 | +} |
| 241 | +
|
| 242 | +target "worker" { |
| 243 | + dockerfile = "Dockerfile.worker" |
| 244 | + platforms = ["linux/amd64", "linux/arm64"] |
| 245 | + tags = ["myrepo/worker:latest"] |
| 246 | + project_id = "project-id-3" |
| 247 | +} |
| 248 | +``` |
| 249 | + |
| 250 | +### Loading images locally |
| 251 | + |
| 252 | +Load specific targets to your local Docker daemon by including the target name after the load flag: |
| 253 | + |
| 254 | +```shell |
| 255 | +depot bake --load app |
| 256 | +``` |
| 257 | + |
| 258 | +This only loads the specified target, not all targets in the bake file. |
| 259 | + |
| 260 | +### Using the Depot Registry with bake |
| 261 | + |
| 262 | +You can save built images to the [Depot Registry](/docs/registry/overview) for later use: |
| 263 | + |
| 264 | +```shell |
| 265 | +depot bake --save --metadata-file=build.json |
| 266 | +``` |
| 267 | + |
| 268 | +If you want to specify a specific tag for the images being stored in the registry, you can do so by using the `--save-tag` flag: |
| 269 | + |
| 270 | +```shell |
| 271 | +depot bake --save --save-tag myrepo/app:v1.0.0 |
| 272 | +``` |
| 273 | + |
| 274 | +You can pull specific targets out of the Depot Registry later using the [`depot pull`](/docs/cli/reference#depot-pull) command: |
| 275 | + |
| 276 | +```shell |
| 277 | +depot pull --project <project-id> --target app,db <build-id> |
| 278 | +``` |
| 279 | + |
| 280 | +Or push to your registry after tests pass: |
| 281 | + |
| 282 | +```shell |
| 283 | +depot push --project <project-id> --target app \ |
| 284 | + --tag myregistry/app:v1.0.0 <build-id> |
| 285 | +``` |
| 286 | + |
| 287 | +### Passing build arguments (i.e. `--build-arg`) to a target |
| 288 | + |
| 289 | +You can pass build arguments to your targets in the bake file using the `args` block. This is useful for passing environment variables or other configuration options to your Docker builds. |
| 290 | + |
| 291 | +```hcl |
| 292 | +target "app" { |
| 293 | + args = { |
| 294 | + NODE_VERSION = "18" |
| 295 | + ENV = "production" |
| 296 | + } |
| 297 | +} |
| 298 | +``` |
| 299 | + |
| 300 | +## GitHub Actions integration |
| 301 | + |
| 302 | +You can use the [`depot/bake-action`](https://github.com/depot/bake-action) in your GitHub Actions workflows to leverage `depot bake` for building your bake files with our [Docker build service](/products/container-builds): |
| 303 | + |
| 304 | +```yaml |
| 305 | +name: Build images |
| 306 | +on: push |
| 307 | +
|
| 308 | +jobs: |
| 309 | + bake: |
| 310 | + runs-on: ubuntu-latest |
| 311 | + permissions: |
| 312 | + id-token: write |
| 313 | + contents: read |
| 314 | + steps: |
| 315 | + - uses: actions/checkout@v4 |
| 316 | + - uses: depot/setup-action@v1 |
| 317 | + - uses: depot/bake-action@v1 |
| 318 | + with: |
| 319 | + file: docker-bake.hcl |
| 320 | + push: true |
| 321 | +``` |
| 322 | + |
| 323 | +## Tips and best practices |
| 324 | + |
| 325 | +1. **Use groups** to organize related targets and build them together |
| 326 | +2. **Leverage inheritance** with `inherits` to reduce duplication |
| 327 | +3. **Use contexts** for shared base images to maximize deduplication |
| 328 | +4. **Set platforms explicitly** to ensure consistent multi-platform builds |
| 329 | +5. **Use variables** for configuration that changes between environments |
| 330 | +6. **Use multiple Depot projects** to shard builds across different BuildKit hosts for resource intensive builds |
| 331 | +7. **Save to ephemeral registry** in CI to build once and push after tests |
| 332 | + |
| 333 | +## Next steps |
| 334 | + |
| 335 | +- Learn more about [BuildKit parallelization](/blog/buildkit-in-depth) |
| 336 | +- Explore the [full bake syntax reference](/blog/buildx-bake-deep-dive) |
| 337 | +- Check out how to get faster container builds with [`depot/bake-action`](/docs/container-builds/reference/github-actions) |
0 commit comments