    def build(self, **attrs: t.Any) -> bytes | None:
        """
        Build the OCI image, and returns the output.
        """
        context_path = attrs.get("context_path", None)
        use_sudo = attrs.pop("_run_as_root", False)
        assert context_path is not None, "context_path must be provided."
        cmds = Arguments([self.binary, *self.build_cmd])
        if use_sudo:
            cmds = ["sudo"] + cmds
        cmds.extend(self.construct_build_args(**attrs))
        logger.debug(
            "%s build cmd: '%s'", self.binary.split(os.sep)[-1], " ".join(cmds)
        )

        # We will always update suprocess environment into
        # default builder environment. This ensure that we
        # respect the user's environment.
        subprocess_env = os.environ.copy()
        env = self.env.copy()
        env.update(subprocess_env)
        commands = list(map(str, cmds))

        try:
            # We need to also respect DOCKER_BUILDKIT environment here
            # to stream logs
            if not self.enable_buildkit or (
                "DOCKER_BUILDKIT" in env and env["DOCKER_BUILDKIT"] == "0"
            ):
                return self.stream_logs(commands, cwd=context_path, env=env).stdout
            else:
                return subprocess.check_output(commands, cwd=context_path, env=env)
        except subprocess.CalledProcessError as e:
            if e.stderr:
                raise BentoMLException(e.stderr.decode("utf-8")) from None
            raise BentoMLException(str(e)) from None
Build the OCI image, and returns the output.
src/bentoml/_internal/container/base.py