Repository: pantsbuild/pants

Issue:
Support for additional Docker build options
**Is your feature request related to a problem? Please describe.**

Pants users have requested support for passing additional options to Docker build. 
- request for `--platform` option - https://github.com/pantsbuild/pants/issues/17539
- request for network and host override - https://pantsbuild.slack.com/archives/C046T6T9U/p1680209250680309
- request for `--no-cache` - https://pantsbuild.slack.com/archives/C046T6T9U/p1686776926633339

Creating this issue as I am happy to volunteer to implement these, but I think it's worth deciding on an approach first. 

**Describe the solution you'd like**

It would be desirable for these options to be available on the `docker_image` target. In some cases, being able to set the option globally via docker backend config may also be helpful. Based on analysis below and requests above, the following options should be prioritised:
- additional host ip mappings
- network mode
- no-cache 
- platform

**Describe alternatives you've considered**

It is possible to use a shim script around the Docker CLI as described here - https://pantsbuild.slack.com/archives/C046T6T9U/p1680209250680309, however it is more difficult to use.

**Additional context**

Support for [buildx](https://docs.docker.com/engine/reference/commandline/buildx_build/) has also been [requested](https://github.com/pantsbuild/pants/issues/15199). The buildx build command has different options to the [standard](https://docs.docker.com/engine/reference/commandline/build/) build command.

Here is an [analysis of the options across both commands](https://docs.google.com/spreadsheets/d/1anjf-Y1Z5ft-uazABiAb54gJ6CxlV1g1o9-yljB8u9c/edit?usp=sharing), along with some suggested names (aliases) for new options. 

**Scope considerations**

Buildx build is now the default in the latest Docker Desktop - it would be better to focus on supporting that going forward - i.e. don't implement options that are only in the standard build command. 

Recommend keeping cache options out of scope of this issue as buildx support should probably be implemented first, and then need to look at implementation of `--cache-from` and `--cache-to` with Pants targets.



Discussion:

Resolving patch:
diff --git a/src/python/pants/backend/docker/goals/package_image.py b/src/python/pants/backend/docker/goals/package_image.py
--- a/src/python/pants/backend/docker/goals/package_image.py
+++ b/src/python/pants/backend/docker/goals/package_image.py
@@ -313,6 +313,7 @@ def get_build_options(
     field_set: DockerPackageFieldSet,
     global_target_stage_option: str | None,
     global_build_hosts_options: dict | None,
+    global_build_no_cache_option: bool | None,
     target: Target,
 ) -> Iterator[str]:
     # Build options from target fields inheriting from DockerBuildOptionFieldMixin
@@ -355,6 +356,9 @@ def get_build_options(
     if target_stage:
         yield from ("--target", target_stage)
 
+    if global_build_no_cache_option:
+        yield "--no-cache"
+
 
 @rule
 async def build_docker_image(
@@ -418,6 +422,7 @@ async def build_docker_image(
                 field_set=field_set,
                 global_target_stage_option=options.build_target_stage,
                 global_build_hosts_options=options.build_hosts,
+                global_build_no_cache_option=options.build_no_cache,
                 target=wrapped_target.target,
             )
         ),
diff --git a/src/python/pants/backend/docker/subsystems/docker_options.py b/src/python/pants/backend/docker/subsystems/docker_options.py
--- a/src/python/pants/backend/docker/subsystems/docker_options.py
+++ b/src/python/pants/backend/docker/subsystems/docker_options.py
@@ -191,6 +191,10 @@ def env_vars(self) -> tuple[str, ...]:
             """
         ),
     )
+    build_no_cache = BoolOption(
+        default=False,
+        help="Do not use the Docker cache when building images.",
+    )
     build_verbose = BoolOption(
         default=False,
         help="Whether to log the Docker output to the console. If false, only the image ID is logged.",


Test patch:
diff --git a/src/python/pants/backend/docker/goals/package_image_test.py b/src/python/pants/backend/docker/goals/package_image_test.py
--- a/src/python/pants/backend/docker/goals/package_image_test.py
+++ b/src/python/pants/backend/docker/goals/package_image_test.py
@@ -170,6 +170,7 @@ def mock_get_info_file(request: CreateDigest) -> Digest:
         opts.setdefault("build_target_stage", None)
         opts.setdefault("build_hosts", None)
         opts.setdefault("build_verbose", False)
+        opts.setdefault("build_no_cache", False)
         opts.setdefault("env_vars", [])
 
         docker_options = create_subsystem(
@@ -1011,6 +1012,45 @@ def check_docker_proc(process: Process):
     )
 
 
+def test_docker_build_no_cache_option(rule_runner: RuleRunner) -> None:
+    rule_runner.set_options(
+        [],
+        env={
+            "PANTS_DOCKER_BUILD_NO_CACHE": "true",
+        },
+    )
+    rule_runner.write_files(
+        {
+            "docker/test/BUILD": dedent(
+                """\
+                docker_image(
+                  name="img1",
+                )
+                """
+            ),
+        }
+    )
+
+    def check_docker_proc(process: Process):
+        assert process.argv == (
+            "/dummy/docker",
+            "build",
+            "--pull=False",
+            "--no-cache",
+            "--tag",
+            "img1:latest",
+            "--file",
+            "docker/test/Dockerfile",
+            ".",
+        )
+
+    assert_build(
+        rule_runner,
+        Address("docker/test", target_name="img1"),
+        process_assertions=check_docker_proc,
+    )
+
+
 def test_docker_build_hosts_option(rule_runner: RuleRunner) -> None:
     rule_runner.set_options(
         [],