198 lines
5.6 KiB
Python
Executable File
198 lines
5.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
import argparse
|
|
import re
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
from jinja2 import Environment, FileSystemLoader, StrictUndefined
|
|
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser(
|
|
description="Renders dynamo Dockerfiles from templates"
|
|
)
|
|
parser.add_argument(
|
|
"--framework",
|
|
type=str,
|
|
default="vllm",
|
|
choices=["dynamo", "vllm", "sglang", "trtllm"],
|
|
help="Dockerfile framework to use",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--device",
|
|
type=str,
|
|
default="cuda",
|
|
choices=["cuda", "xpu"],
|
|
help="Dockerfile device to use",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--target",
|
|
type=str,
|
|
default="runtime",
|
|
help="Dockerfile target to use. Non-exhaustive examples: [runtime, dev, local-dev]",
|
|
)
|
|
parser.add_argument(
|
|
"--platform",
|
|
type=str,
|
|
default="amd64",
|
|
help="Dockerfile platform to use. [amd64, arm64]",
|
|
)
|
|
parser.add_argument(
|
|
"--cuda-version",
|
|
type=str,
|
|
default="12.9",
|
|
choices=["12.9", "13.0", "13.1"],
|
|
help="CUDA version to use. [12.9 or 13.0 for vllm and sglang, 13.1 for trtllm]",
|
|
)
|
|
parser.add_argument("--make-efa", action="store_true", help="Enable AWS EFA")
|
|
parser.add_argument(
|
|
"--output-short-filename",
|
|
action="store_true",
|
|
help="Output filename is rendered.Dockerfile instead of <framework>-<target>-cuda<cuda_version>-<arch>-rendered.Dockerfile",
|
|
)
|
|
parser.add_argument(
|
|
"--show-result",
|
|
action="store_true",
|
|
help="Prints the rendered Dockerfile to stdout.",
|
|
)
|
|
args = parser.parse_args()
|
|
return args
|
|
|
|
|
|
def validate_args(args):
|
|
valid_inputs = {
|
|
"vllm": {
|
|
"device": ["cuda", "xpu"],
|
|
"target": [
|
|
"runtime",
|
|
"dev",
|
|
"local-dev",
|
|
"framework",
|
|
"wheel_builder",
|
|
"base",
|
|
],
|
|
"cuda_version": ["12.9", "13.0"],
|
|
},
|
|
"trtllm": {
|
|
"device": ["cuda"],
|
|
"target": [
|
|
"runtime",
|
|
"dev",
|
|
"local-dev",
|
|
"framework",
|
|
"wheel_builder",
|
|
"base",
|
|
],
|
|
"cuda_version": ["13.1"],
|
|
},
|
|
"sglang": {
|
|
"device": ["cuda"],
|
|
"target": [
|
|
"runtime",
|
|
"dev",
|
|
"local-dev",
|
|
"wheel_builder",
|
|
"base",
|
|
],
|
|
"cuda_version": ["12.9", "13.0"],
|
|
},
|
|
"dynamo": {
|
|
"device": ["cuda"],
|
|
"target": [
|
|
"runtime",
|
|
"dev",
|
|
"local-dev",
|
|
"frontend",
|
|
"wheel_builder",
|
|
"base",
|
|
],
|
|
"cuda_version": ["12.9", "13.0"],
|
|
},
|
|
}
|
|
|
|
if args.framework in valid_inputs:
|
|
if (
|
|
args.target in valid_inputs[args.framework]["target"]
|
|
and args.cuda_version in valid_inputs[args.framework]["cuda_version"]
|
|
and args.device in valid_inputs[args.framework]["device"]
|
|
):
|
|
return
|
|
|
|
raise ValueError(
|
|
f"Invalid input combination: [framework={args.framework},target={args.target},cuda_version={args.cuda_version},device={args.device}]"
|
|
)
|
|
|
|
raise ValueError(
|
|
f"Invalid input combination: [framework={args.framework},target={args.target},cuda_version={args.cuda_version},device={args.device}]"
|
|
)
|
|
|
|
|
|
def render(args, context, script_dir):
|
|
env = Environment(
|
|
loader=FileSystemLoader(script_dir),
|
|
trim_blocks=False,
|
|
lstrip_blocks=True,
|
|
undefined=StrictUndefined, # Raise an error if a variable in the template is not provided in the context
|
|
)
|
|
template = env.get_template("Dockerfile.template")
|
|
rendered = template.render(
|
|
context=context,
|
|
framework=args.framework,
|
|
device=args.device,
|
|
target=args.target,
|
|
platform=args.platform,
|
|
cuda_version=args.cuda_version,
|
|
make_efa=args.make_efa,
|
|
)
|
|
# Replace all instances of 3+ newlines with 2 newlines
|
|
cleaned = re.sub(r"\n{3,}", "\n\n", rendered)
|
|
|
|
if args.output_short_filename:
|
|
filename = "rendered.Dockerfile"
|
|
else:
|
|
filename = f"{args.framework}-{args.target}-{args.device}{args.cuda_version}-{args.platform}-rendered.Dockerfile"
|
|
|
|
with open(f"{script_dir}/{filename}", "w") as f:
|
|
f.write(cleaned)
|
|
|
|
if args.show_result:
|
|
print("##############")
|
|
print("# Dockerfile #")
|
|
print("##############")
|
|
print(cleaned)
|
|
print("##############")
|
|
|
|
print(f"INFO: Generated Dockerfile written to {script_dir}/{filename}")
|
|
|
|
return
|
|
|
|
|
|
def main():
|
|
args = parse_args()
|
|
validate_args(args)
|
|
# Clear cuda version for non-cuda device
|
|
if args.device != "cuda":
|
|
args.cuda_version = ""
|
|
script_dir = Path(__file__).parent
|
|
with open(f"{script_dir}/context.yaml", "r") as f:
|
|
context = yaml.safe_load(f)
|
|
|
|
render(args, context, script_dir)
|
|
|
|
if args.target == "local-dev":
|
|
print(
|
|
"INFO: Remember to add --build-arg values for USER_UID and USER_GID when building a local-dev image!"
|
|
)
|
|
print(
|
|
" Recommendation: --build-arg USER_UID=$(id -u) --build-arg USER_GID=$(id -g)"
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|