Repository: kreuzwerker/terraform-provider-docker

Issue:
feat: Add support for additional docker_image build contexts
### Community Note
* Please vote on this issue by adding a 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to the original issue to help the community and maintainers prioritize this request
* Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
* If you are interested in working on this issue or have submitted a pull request, please leave a comment

### Description
Docker now has the ability to use multiple build contexts.  Add support for this feature.
Either change build.context to an array or add build.additional_contexts.

### New or Affected Resource(s)
* docker_image

### Potential Terraform Configuration

<!--- Information about code formatting: https://help.github.com/articles/basic-writing-and-formatting-syntax/#quoting-code --->

```hcl
resource "docker_image" "zoo" {
  name = "zoo"
  build {
    context = [".", "../someotherdir"]
    #OR (backwards-compatible version)
    additional_contexts = ["../foo", "../bar"]
  }
}
```

### References
[https://www.docker.com/blog/dockerfiles-now-support-multiple-build-contexts]



Discussion:

Solution patch:
diff --git a/docs/resources/image.md b/docs/resources/image.md
index 6317808..ea8bc51 100644
--- a/docs/resources/image.md
+++ b/docs/resources/image.md
@@ -121,6 +121,7 @@ Required:
 
 Optional:
 
+- `additional_contexts` (List of String) A list of additional build contexts. Only supported when using a buildx builder. Example: `["name=path", "src = https://example.org"}`. Please see https://docs.docker.com/reference/cli/docker/buildx/build/#build-context for more information.
 - `auth_config` (Block List) The configuration for the authentication (see [below for nested schema](#nestedblock--build--auth_config))
 - `build_args` (Map of String) Pairs for build-time variables in the form of `ENDPOINT : "https://example.com"`
 - `build_id` (String) BuildID is an optional identifier that can be passed together with the build request. The same identifier can be used to gracefully cancel the build with the cancel request.
diff --git a/internal/provider/docker_buildx_build.go b/internal/provider/docker_buildx_build.go
index c8302f3..e6cc938 100644
--- a/internal/provider/docker_buildx_build.go
+++ b/internal/provider/docker_buildx_build.go
@@ -227,6 +227,10 @@ func mapBuildAttributesToBuildOptions(buildAttributes map[string]interface{}, im
 		options.tags = append(options.tags, t.(string))
 	}
 
+	if contexts, ok := buildAttributes["additional_contexts"].([]interface{}); ok {
+		options.contexts = interfaceArrayToStringArray(contexts)
+	}
+
 	if builder, ok := buildAttributes["builder"].(string); ok {
 		options.builder = builder
 	}
diff --git a/internal/provider/resource_docker_image.go b/internal/provider/resource_docker_image.go
index 53996d1..08ffad6 100644
--- a/internal/provider/resource_docker_image.go
+++ b/internal/provider/resource_docker_image.go
@@ -328,6 +328,16 @@ func resourceDockerImage() *schema.Resource {
 							Required:    true,
 							ForceNew:    true,
 						},
+						"additional_contexts": {
+							Type:        schema.TypeList,
+							Description: "A list of additional build contexts. Only supported when using a buildx builder. Example: `[\"name=path\", \"src = https://example.org\"}`. Please see https://docs.docker.com/reference/cli/docker/buildx/build/#build-context for more information.",
+							Optional:    true,
+							ForceNew:    true,
+							Elem: &schema.Schema{
+								Type:        schema.TypeString,
+								Description: "An additional context in the form of `key=value`",
+							},
+						},
 						"labels": {
 							Type:        schema.TypeMap,
 							Description: "User-defined key/value metadata",
diff --git a/scripts/testing/buildx_additional_context/file.txt b/scripts/testing/buildx_additional_context/file.txt
new file mode 100644
index 0000000..e69de29


Test patch:
diff --git a/internal/provider/resource_docker_image_test.go b/internal/provider/resource_docker_image_test.go
index 976ba21..e5f4ca4 100644
--- a/internal/provider/resource_docker_image_test.go
+++ b/internal/provider/resource_docker_image_test.go
@@ -609,6 +609,25 @@ func TestAccDockerImageResource_buildxCacheFromCacheTo(t *testing.T) {
 	})
 }
 
+func TestAccDockerImageResource_buildxAdditionalContexts(t *testing.T) {
+	wd, _ := os.Getwd()
+	context := strings.ReplaceAll((filepath.Join(wd, "..", "..", "scripts", "testing", "docker_registry_image_context")), "\\", "\\\\")
+	additional_context := strings.ReplaceAll((filepath.Join(wd, "..", "..", "scripts", "testing", "buildx_additional_context")), "\\", "\\\\")
+
+	resource.Test(t, resource.TestCase{
+		PreCheck:          func() { testAccPreCheck(t) },
+		ProviderFactories: providerFactories,
+		Steps: []resource.TestStep{
+			{
+				Config: fmt.Sprintf(loadTestConfiguration(t, RESOURCE, "docker_image", "testAccDockerImageAdditionalContexts"), context, context, additional_context),
+				Check: resource.ComposeTestCheckFunc(
+					resource.TestCheckResourceAttrSet("docker_image.test_additional_contexts", "image_id"),
+				),
+			},
+		},
+	})
+}
+
 // Test for https://github.com/kreuzwerker/terraform-provider-docker/issues/249
 func TestAccDockerImageResource_whitelistDockerignore(t *testing.T) {
 	name := "tftest-dockerregistryimage-whitelistdockerignore:1.0"
diff --git a/testdata/resources/docker_image/testAccDockerImageAdditionalContexts.tf b/testdata/resources/docker_image/testAccDockerImageAdditionalContexts.tf
new file mode 100644
index 0000000..96073aa
--- /dev/null
+++ b/testdata/resources/docker_image/testAccDockerImageAdditionalContexts.tf
@@ -0,0 +1,20 @@
+resource "docker_buildx_builder" "foo" {
+  name = "foo"
+  docker_container {
+    image = "moby/buildkit:v0.22.0"
+  }
+  use = true
+  bootstrap = true
+}
+
+resource "docker_image" "test_additional_contexts" {
+  name = "alpine:latest"
+  build {
+    context      = "%s"
+    dockerfile   = "%s/Dockerfile"
+    force_remove = true
+    builder = docker_buildx_builder.foo.name
+
+    additional_contexts = ["second=%s"]
+  }
+}