Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for adding arbitrary docker build flags #21839

Open
kuza55 opened this issue Jan 15, 2025 · 1 comment
Open

Add support for adding arbitrary docker build flags #21839

kuza55 opened this issue Jan 15, 2025 · 1 comment
Labels
backend: Docker Docker backend-related issues enhancement

Comments

@kuza55
Copy link

kuza55 commented Jan 15, 2025

Is your feature request related to a problem? Please describe.
Docker has a lot of different flags, most of which are not officially supported via pants, I'd like to be able to use them without needing code changes to pants.

extra_runs_args got added in #20440 but the build args version was never added.

Describe the solution you'd like
I'd like docker_image and pants.toml to get some extra parameters for extra_command_line_build_args to be passed to docker build..

Describe alternatives you've considered
Adding every flag to pants that does not need special handling seems wasteful.

@huonw huonw added the backend: Docker Docker backend-related issues label Jan 16, 2025
@huonw
Copy link
Contributor

huonw commented Jan 16, 2025

This does seem sensible.

The hardest bit is probably deciding on a name that doesn't conflict with the existing extra_build_args field (https://www.pantsbuild.org/stable/reference/targets/docker_image#extra_build_args). Maybe extra_docker_build_args or extra_args_for_docker_build are good enough?

Would you like to contribute this?

Breadcrumbs:

  • a new field like extra_run_args:
    class DockerImageRunExtraArgsField(StringSequenceField):
    alias: ClassVar[str] = "extra_run_args"
    default = ()
    help = help_text(
    lambda: f"Extra arguments to pass into the invocation of `docker run`. These are in addition to those at the `[{DockerOptions.options_scope}].run_args`"
    )
  • maybe expand get_build_options to yield them too:
    def get_build_options(
    context: DockerBuildContext,
    field_set: DockerPackageFieldSet,
    global_target_stage_option: str | None,
    global_build_hosts_options: dict | None,
    global_build_no_cache_option: bool | None,
    use_buildx_option: bool,
    target: Target,
    ) -> Iterator[str]:
    # Build options from target fields inheriting from DockerBuildOptionFieldMixin
    for field_type in target.field_types:
    if issubclass(field_type, DockerBuildKitOptionField):
    if use_buildx_option is not True:
    if target[field_type].value != target[field_type].default:
    raise DockerImageOptionValueError(
    f"The {target[field_type].alias} field on the = `{target.alias}` target in `{target.address}` was set to `{target[field_type].value}`"
    f" and buildx is not enabled. Buildx must be enabled via the Docker subsystem options in order to use this field."
    )
    else:
    # Case where BuildKit option has a default value - still should not be generated
    continue
    if issubclass(
    field_type,
    (
    DockerBuildOptionFieldMixin,
    DockerBuildOptionFieldMultiValueDictMixin,
    DockerBuildOptionFieldListOfMultiValueDictMixin,
    DockerBuildOptionFieldValueMixin,
    DockerBuildOptionFieldMultiValueMixin,
    DockerBuildOptionFlagFieldMixin,
    ),
    ):
    source = InterpolationContext.TextSource(
    address=target.address, target_alias=target.alias, field_alias=field_type.alias
    )
    format = partial(
    context.interpolation_context.format,
    source=source,
    error_cls=DockerImageOptionValueError,
    )
    yield from target[field_type].options(format, global_build_hosts_options=global_build_hosts_options) # type: ignore[attr-defined]
    # Target stage
    target_stage = None
    if global_target_stage_option in context.stages:
    target_stage = global_target_stage_option
    elif field_set.target_stage.value:
    target_stage = field_set.target_stage.value
    if target_stage not in context.stages:
    raise DockerBuildTargetStageError(
    f"The {field_set.target_stage.alias!r} field in `{target.alias}` "
    f"{field_set.address} was set to {target_stage!r}"
    + (
    f", but there is no such stage in `{context.dockerfile}`. "
    f"Available stages: {', '.join(context.stages)}."
    if context.stages
    else f", but there are no named stages in `{context.dockerfile}`."
    )
    )
    if target_stage:
    yield from ("--target", target_stage)
    if global_build_no_cache_option:
    yield "--no-cache"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend: Docker Docker backend-related issues enhancement
Projects
None yet
Development

No branches or pull requests

2 participants