def containerize_command(  # type: ignore
    bento_tag: str,
    image_tag: tuple[str] | None,
    backend: DefaultBuilder,
    enable_features: tuple[str] | None,
    run_as_root: bool,
    _memoized: dict[str, t.Any],
) -> None:
    """Containerizes given Bento into an OCI-compliant container, with any given OCI builder.

    \b

    ``BENTO`` is the target BentoService to be containerized, referenced by its name
    and version in format of name:version. For example: ``iris_classifier:v1.2.0``

    \b
    ``bentoml containerize`` command also supports the use of the ``latest`` tag
    which will automatically use the last built version of your Bento.

    \b
    You can provide a tag for the image built by Bento using the
    ``--image-tag`` flag.

    \b
    You can also prefix the tag with a hostname for the repository you wish to push to.

    .. code-block:: bash

        $ bentoml containerize iris_classifier:latest -t repo-address.com:username/iris

    This would build an image called ``username/iris:latest`` and push it to docker repository at ``repo-address.com``.

    \b
    By default, the ``containerize`` command will use the current credentials provided by each backend implementation.

    \b
    ``bentoml containerize`` also leverage BuildKit features such as multi-node
    builds for cross-platform images, more efficient caching, and more secure builds.
    BuildKit will be enabled by default by each backend implementation. To opt-out of BuildKit, set ``DOCKER_BUILDKIT=0``:

    .. code-block:: bash

        $ DOCKER_BUILDKIT=0 bentoml containerize iris_classifier:latest

    \b
    ``bentoml containerize`` is backend-agnostic, meaning that it can use any OCI-compliant builder to build the container image.
    By default, it will use the ``docker`` backend, which will use the local Docker daemon to build the image.
    You can use the ``--backend`` flag to specify a different backend. Note that backend flags will now be unified via ``--opt``.

    ``--opt`` accepts multiple flags, and it works with all backend options.

    \b
    To pass a boolean flag (e.g: ``--no-cache``), use ``--opt no-cache``.

    \b
    To pass a key-value pair (e.g: ``--build-arg FOO=BAR``), use ``--opt build-arg=FOO=BAR`` or ``--opt build-arg:FOO=BAR``. Make sure to quote the value if it contains spaces.

    \b
    To pass a argument with one value (path, integer, etc) (e.g: ``--cgroup-parent cgroupv2``), use ``--opt cgroup-parent=cgroupv2`` or ``--opt cgroup-parent:cgroupv2``.
    """

    # we can filter out all options that are None or False.
    _memoized = {k: v for k, v in _memoized.items() if v}
    logger.debug("Memoized: %s", _memoized)

    # Run healthcheck before containerizing
    # build will also run healthcheck, but we want to fail early.
    try:
        container.health(backend)
    except subprocess.CalledProcessError:
        raise BentoMLException(f"Backend {backend} is not healthy")

    # --progress is not available without BuildKit.
    if not enable_buildkit(backend=backend) and "progress" in _memoized:
        _memoized.pop("progress")
    elif get_debug_mode():
        _memoized["progress"] = "plain"
    _memoized["_run_as_root"] = run_as_root

    features: tuple[str] | None = None
    if enable_features:
        features = tuple(
            itertools.chain.from_iterable(map(lambda s: s.split(","), enable_features))
        )
    result = container.build(
        bento_tag,
        backend=backend,
        image_tag=image_tag,
        features=features,
        **_memoized,
    )

    if result is not None:
        tags = determine_container_tag(bento_tag, image_tag=image_tag)

        container_runtime = backend
        # This logic determines some of the output messages.
        if backend == "buildah":
            if shutil.which("podman") is None:
                logger.warning(
                    "'buildah' are only used to build the image. To run the image, 'podman' is required to be installed (podman not found under PATH). See https://podman.io/getting-started/installation."
                )
                sys.exit(0)
            else:
                container_runtime = "podman"
        elif backend == "buildx":
            # buildx is a syntatic sugar for docker buildx build
            container_runtime = "docker"
        elif backend == "buildctl":
            if shutil.which("docker") is not None:
                container_runtime = "docker"
            elif shutil.which("podman") is not None:
                container_runtime = "podman"
            elif shutil.which("nerdctl") is not None:
                container_runtime = "nerdctl"
            else:
                rich.print(
                    "[yellow]To load image built with 'buildctl' requires one of "
                    "docker, podman, nerdctl (None are found in PATH). "
                    "Make sure they are visible to PATH and try again.[/]",
                )
                sys.exit(0)
            if "output" not in _memoized:
                tmp_path = tempfile.gettempdir()
                type_prefix = "type=oci,name="
                if container_runtime == "docker":
                    type_prefix = "type=docker,name=docker.io/"
                rich.print(
                    "[yellow]Autoconfig is now deprecated and will be removed "
                    "in the next future release. We recommend setting "
                    "output to a tarfile should you wish to load the "
                    "image locally. For example:[/]",
                )
                rich.print(
                    f"[yellow]    bentoml containerize {bento_tag} --backend buildctl --opt output={type_prefix}{tags[0]},dest={tmp_path}/{tags[0].replace(':', '_')}.tar\n"
                    f"    {container_runtime} load -i {tmp_path}/{tags[0].replace(':', '_')}.tar[/]",
                )
                o = subprocess.check_output([container_runtime, "load"], input=result)
                if get_debug_mode():
                    rich.print(o.decode("utf-8").strip())
                sys.exit(0)
            return result

        rich.print(
            f'Successfully built Bento container for [green]"{bento_tag}"[/] with tag(s) "{",".join(tags)}"',
        )
        instructions = (
            "To run your newly built Bento container, run:\n"
            + f"    {container_runtime} run --rm -p 3000:3000 {tags[0]}\n"
        )

        if features is not None and any(
            has_grpc in features
            for has_grpc in ("all", "grpc", "grpc-reflection", "grpc-channelz")
        ):
            instructions += (
                "To serve with gRPC instead, run:\n"
                + f"    {container_runtime} run --rm -p 3000:3000 -p 3001:3001 {tags[0]} serve-grpc"
            )
        rich.print(instructions)
        sys.exit(0)
    raise SystemExit(1)
Containerizes given Bento into an OCI-compliant container, with any given OCI builder.

\b

``BENTO`` is the target BentoService to be containerized, referenced by its name
and version in format of name:version. For example: ``iris_classifier:v1.2.0``

\b
``bentoml containerize`` command also supports the use of the ``latest`` tag
which will automatically use the last built version of your Bento.

\b
You can provide a tag for the image built by Bento using the
``--image-tag`` flag.

\b
You can also prefix the tag with a hostname for the repository you wish to push to.

.. code-block:: bash

$ bentoml containerize iris_classifier:latest -t repo-address.com:username/iris

This would build an image called ``username/iris:latest`` and push it to docker repository at ``repo-address.com``.

\b
By default, the ``containerize`` command will use the current credentials provided by each backend implementation.

\b
``bentoml containerize`` also leverage BuildKit features such as multi-node
builds for cross-platform images, more efficient caching, and more secure builds.
BuildKit will be enabled by default by each backend implementation. To opt-out of BuildKit, set ``DOCKER_BUILDKIT=0``:

.. code-block:: bash

$ DOCKER_BUILDKIT=0 bentoml containerize iris_classifier:latest

\b
``bentoml containerize`` is backend-agnostic, meaning that it can use any OCI-compliant builder to build the container image.
By default, it will use the ``docker`` backend, which will use the local Docker daemon to build the image.
You can use the ``--backend`` flag to specify a different backend. Note that backend flags will now be unified via ``--opt``.

``--opt`` accepts multiple flags, and it works with all backend options.

\b
To pass a boolean flag (e.g: ``--no-cache``), use ``--opt no-cache``.

\b
To pass a key-value pair (e.g: ``--build-arg FOO=BAR``), use ``--opt build-arg=FOO=BAR`` or ``--opt build-arg:FOO=BAR``. Make sure to quote the value if it contains spaces.

\b
To pass a argument with one value (path, integer, etc) (e.g: ``--cgroup-parent cgroupv2``), use ``--opt cgroup-parent=cgroupv2`` or ``--opt cgroup-parent:cgroupv2``.
src/bentoml_cli/containerize.py