spec icon indicating copy to clipboard operation
spec copied to clipboard

Allow option to build image with Docker buildx Bake

Open c-ameron opened this issue 2 years ago • 2 comments

It would be great to allow the option to use Docker's Bake cli tool to build images as well. https://docs.docker.com/engine/reference/commandline/buildx_bake/

In my repos, we're using bake internally to build images (including sourcing remote docker bake files), it would be great to have this option as well so we could have parity with devcontainers.

Could potentially be merged with this feature request on allow extra flags to the buildx command https://github.com/devcontainers/spec/issues/85

Thanks!

c-ameron avatar Sep 26 '23 15:09 c-ameron

This would be awesome! My team is evaluating the use of Docker buildx Bake to segment our Dockerfiles while keeping them DRY by having the build stages defined in one Dockerfile for reuse across all others. However, it becomes tricky if we then want to use the same Dockerfiles with Dev Containers, given that by taking advantage of advance bake file context features, the Dockerfiles themselves may not be as simple to rebuild, in the same manner, using singular docker buildx build command.

Perhaps an additional top level keyword could be use, given that docker buildx bake may not support all the same set of CLI arguments as docker buildx build. This could be make exclusive to the existing keywords image and build. E.g:

{
    "name": "Example",
    // Uncomment to bake image
    "bake": {
        "bakefiles": [ "../docker-bake.hcl" ],
        "target": "foo",
        "pull": "true",
        "set": [
            "target.args.mybuildarg=value",
            "foo*.args.mybuildarg=value",
        ],
    },
    // Uncomment to build image
    "build": {
        "dockerfile": "../Dockerfile",
        "context": "..",
        "target": "foo",
        "cacheFrom": [
            "ghcr.io/pre/built:image"
        ]
    },
    // Uncomment to use pre-built image
    "image": "pre/built:image",
}

One hurtle may be in how current tools auto generate a Dockerfile to define the dev container image by appending subsequent stages to the original Dockerfile. If there is no single Dockerfile, what would be used instead.

I'd propose adding a subsequent target that points the users provided target (or default target if none is specified from the devcontainer.json), that then includes that users provided target as context to base its own Dockerfile with. E.g

docker-bake.hcl - user provided

group "default" {
  targets = ["foo"]
}

target "foo" {
  target = "some-dockerfile-stage"
  dockerfile = "path/to/Dockerfile"
  tags = ["org/repo:tag"]
  push = false
  no-cache = false
  cache-from = [
    "type=registry,ref=ghcr.io/pre/built:image",
  ]
  cache-to = [
    "type=inline",
  ]
  ...
}
...

devcontainer-bake.hcl - auto generated

target "_dev_containers_bake_target" {
  dockerfile = "path/to/Dockerfile-with-features"
  contexts = {
    _DEV_CONTAINERS_BASE_IMAGE = "target:foo"
  }
  target = "dev_containers_target_stage"
  tags = ["vsc-NAME-HASH"]
}

Dockerfile-with-features - auto generated

FROM _DEV_CONTAINERS_BASE_IMAGE AS dev_containers_target_stage
...

Bake command - auto generated

$ docker buildx bake --load \
    --file ../docker-bake.hcl \
    --set=target.args.mybuildarg=value \
    --set=foo*.args.mybuildarg=value \
    --pull \
    --file path/to/devcontainer-bake.hcl \
    _dev_containers_bake_target

cc @chrmarti @samruddhikhandale any thoughts?

ruffsl avatar Apr 14 '24 00:04 ruffsl

Well, in the meantime, I've found using the initializeCommand lifecycle-script to be a decent workaround. E.g:

devcontainer.json

{
    "name": "Example",
    "initializeCommand": ".devcontainer/initialize-command.sh foo",
    "image": "vsc:devcontainer",
}

initialize-command.sh

#!/bin/bash

# Immediately catch all errors
set -eo pipefail

# Uncomment for debugging
# set -x
# env

# Use first argument as target name
target=$1

# Bake the target and export locally to static tag
docker buildx bake --load \
    --file docker-bake.hcl \
    --set $target.tags=vsc:devcontainer \
    $target

ruffsl avatar Apr 15 '24 03:04 ruffsl