Skip to content

Commit ff2e1ae

Browse files
authored
Merge pull request #673 from basetenlabs/bump-version-0.7.8
Release 0.7.8
2 parents e7485f3 + 3160b58 commit ff2e1ae

11 files changed

+112
-15
lines changed

docs/guides/base-images.mdx

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
title: How to use base images
3+
description: "A guide to configuring a base image for your truss"
4+
---
5+
6+
7+
Model serving enviroments will often be standardized as container images to avoid wrangling python, system, and other requirements needed to run your model on every deploy.
8+
Leverage your existing container artifacts by bringing your own base image to Truss.
9+
10+
## Setting a base image in config.yaml
11+
12+
To specify a base image to build a truss container image from in your `config.yaml` configure a `base_image`.
13+
14+
```yaml config.yaml
15+
base_image:
16+
image: <image_name:tag>
17+
python_executable_path: <path-to-python>
18+
```
19+
20+
where `python_executable_path` is a path to a python executable with which to run your server.
21+
22+
## Example usage
23+
24+
This [example truss](https://github.com/basetenlabs/truss/tree/main/examples/nemo-titanet) demonstrates how to properly configure a base image for Nvidia NeMo TitaNet:
25+
26+
```yaml config.yaml
27+
base_image:
28+
image: nvcr.io/nvidia/nemo:23.03
29+
python_executable_path: /usr/bin/python
30+
apply_library_patches: true
31+
bundled_packages_dir: packages
32+
data_dir: data
33+
requirements:
34+
- PySoundFile
35+
live_reload: false
36+
resources:
37+
accelerator: T4
38+
cpu: 2500m
39+
memory: 4512Mi
40+
use_gpu: true
41+
secrets: {}
42+
spec_version: '2.0'
43+
system_packages:
44+
- python3.8-venv
45+
```
46+
47+
## Configuring private base images with build time secrets
48+
49+
Secrets of the form `DOCKER_REGISTRY_<REGISTRY_URL>` will be supplied to your model build to authenticate image pulls from private container registries.
50+
For information on where to store secret values see the [secrets guide](secrets#storing-secrets-on-your-remote).
51+
52+
For example, to configure docker credentials to a private dockerhub repository your `config.yaml` should include the following secret and placeholder:
53+
54+
```yaml config.yaml
55+
secrets:
56+
DOCKER_REGISTRY_https://index.docker.io/v1/: null
57+
```
58+
59+
along with a configured Baseten secret `DOCKER_REGISTRY_https://index.docker.io/v1/` with a base64 encoded `username:password` secret value:
60+
61+
```sh
62+
echo -n 'username:password' | base64
63+
```
64+
65+
To add docker credentials for gcloud artifact registry provide an [access token](https://cloud.google.com/artifact-registry/docs/docker/authentication#token) as the secret value.
66+
For example, to configure authentication for a repository in `us-west2` your `config.yaml` should include the following secret and placeholder:
67+
68+
```yaml config.yaml
69+
secrets:
70+
DOCKER_REGISTRY_us-west2-docker.pkg.dev: null
71+
```

docs/mint.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@
6767
{
6868
"group": "Guides",
6969
"pages": [
70-
"guides/secrets"
70+
"guides/secrets",
71+
"guides/base-images"
7172
]
7273
},
7374
{

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "truss"
3-
version = "0.7.7"
3+
version = "0.7.8"
44
description = "A seamless bridge from model development to model delivery"
55
license = "MIT"
66
readme = "README.md"

truss/contexts/image_builder/serving_image_builder.py

+2
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ def create_tgi_build_dir(
255255
data_dir = build_dir / "data"
256256
credentials_file = data_dir / "service_account.json"
257257
dockerfile_content = dockerfile_template.render(
258+
config=config,
258259
hf_access_token=hf_access_token,
259260
models=model_files,
260261
hf_cache=config.hf_cache,
@@ -312,6 +313,7 @@ def create_vllm_build_dir(
312313
data_dir = build_dir / "data"
313314
credentials_file = data_dir / "service_account.json"
314315
dockerfile_content = dockerfile_template.render(
316+
config=config,
315317
hf_access_token=hf_access_token,
316318
models=model_files,
317319
should_install_server_requirements=True,

truss/templates/shared/secrets_resolver.py

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import os
22
from collections.abc import Mapping
33
from pathlib import Path
4-
from typing import Dict
4+
from typing import Dict, Optional
5+
6+
SECRETS_DOC_LINK = "https://truss.baseten.co/docs/using-secrets"
57

68

79
class SecretNotFound(Exception):
@@ -17,7 +19,7 @@ def get_secrets(config: Dict):
1719
return Secrets(config.get("secrets", {}))
1820

1921
@staticmethod
20-
def _resolve_secret(secret_name: str, default_value: str):
22+
def _resolve_secret(secret_name: str, default_value: Optional[str]):
2123
secret_value = default_value
2224
secret_env_var_name = SecretsResolver.SECRET_ENV_VAR_PREFIX + secret_name
2325
if secret_env_var_name in os.environ:
@@ -39,15 +41,11 @@ def __init__(self, base_secrets: Dict[str, str]):
3941

4042
def __getitem__(self, key: str) -> str:
4143
if key not in self._base_secrets:
42-
# Note this is the case where the secrets are not specified in
43-
# config.yaml
44-
raise SecretNotFound(f"Secret '{key}' not specified in the config.")
44+
raise SecretNotFound(_secret_missing_error_message(key))
4545

4646
found_secret = SecretsResolver._resolve_secret(key, self._base_secrets[key])
4747
if not found_secret:
48-
raise SecretNotFound(
49-
f"Secret '{key}' not found. Please check available secrets."
50-
)
48+
raise SecretNotFound(_secret_missing_error_message(key))
5149

5250
return found_secret
5351

@@ -58,3 +56,13 @@ def __iter__(self):
5856

5957
def __len__(self):
6058
return len(self._base_secrets)
59+
60+
61+
def _secret_missing_error_message(key: str) -> str:
62+
return f"""
63+
Secret '{key}' not found. Please ensure that:
64+
* Secret '{key}' is defined in the 'secrets' section of the Truss config file
65+
* The model was pushed with the --trusted flag
66+
* Secret '{key}' is defined in the secret manager
67+
Read more about secrets here: {SECRETS_DOC_LINK}.
68+
"""

truss/templates/tgi/proxy.conf.jinja

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
server {
3+
# We use the proxy_read_timeout directive here (instead of proxy_send_timeout) as it sets the timeout for reading a response from the proxied server vs. setting a timeout for sending a request to the proxied server.
34
listen 8080;
45

56
# Liveness
@@ -11,6 +12,7 @@ server {
1112
# Readiness
1213
location ~ ^/v1/models/model$ {
1314
proxy_redirect off;
15+
proxy_read_timeout 300s;
1416

1517
rewrite ^/v1/models/model$ /health break;
1618

@@ -20,6 +22,7 @@ server {
2022
# Predict
2123
location ~ ^/v1/models/model:predict$ {
2224
proxy_redirect off;
25+
proxy_read_timeout 300s;
2326

2427
rewrite ^/v1/models/model:predict$ /{{endpoint}} break;
2528

truss/templates/tgi/tgi.Dockerfile.jinja

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ COPY ./proxy.conf /etc/nginx/conf.d/proxy.conf
1616
RUN mkdir -p /var/log/supervisor
1717
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
1818

19+
{% for env_var_name, env_var_value in config.environment_variables.items() %}
20+
ENV {{ env_var_name }} {{ env_var_value }}
21+
{% endfor %}
22+
1923
ENV SERVER_START_CMD /usr/bin/supervisord
2024

2125
{%- if hf_cache %}

truss/templates/vllm/proxy.conf.jinja

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
21
server {
2+
# We use the proxy_read_timeout directive here (instead of proxy_send_timeout) as it sets the timeout for reading a response from the proxied server vs. setting a timeout for sending a request to the proxied server.
33
listen 8080;
44

55
# Liveness
@@ -11,6 +11,7 @@ server {
1111
# Readiness
1212
location ~ ^/v1/models/model$ {
1313
proxy_redirect off;
14+
proxy_read_timeout 300s;
1415

1516
rewrite ^/v1/models/model$ /v1/models break;
1617

@@ -20,6 +21,7 @@ server {
2021
# Predict
2122
location ~ ^/v1/models/model:predict$ {
2223
proxy_redirect off;
24+
proxy_read_timeout 300s;
2325

2426
rewrite ^/v1/models/model:predict$ {{server_endpoint}} break;
2527

truss/templates/vllm/vllm.Dockerfile.jinja

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ COPY ./proxy.conf /etc/nginx/conf.d/proxy.conf
1616
RUN mkdir -p /var/log/supervisor
1717
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
1818

19+
{% for env_var_name, env_var_value in config.environment_variables.items() %}
20+
ENV {{ env_var_name }} {{ env_var_value }}
21+
{% endfor %}
22+
1923
ENV SERVER_START_CMD /usr/bin/supervisord
2024

2125
{%- if hf_cache %}

truss/tests/test_model_inference.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,9 @@ def predict(self, request):
336336
"""
337337

338338
config_with_no_secret = "model_name: secrets-truss"
339+
missing_secret_error_message = """Secret 'secret' not found. Please ensure that:
340+
* Secret 'secret' is defined in the 'secrets' section of the Truss config file
341+
* The model was pushed with the --trusted flag"""
339342

340343
with ensure_kill_all(), tempfile.TemporaryDirectory(dir=".") as tmp_work_dir:
341344
truss_dir = Path(tmp_work_dir, "truss")
@@ -371,7 +374,7 @@ def predict(self, request):
371374

372375
assert "error" in response.json()
373376

374-
assert_logs_contain_error(container.logs(), "not specified in the config")
377+
assert_logs_contain_error(container.logs(), missing_secret_error_message)
375378
assert "Internal Server Error" in response.json()["error"]
376379

377380
with ensure_kill_all(), tempfile.TemporaryDirectory(dir=".") as tmp_work_dir:
@@ -390,9 +393,7 @@ def predict(self, request):
390393
response = requests.post(full_url, json={})
391394
assert response.status_code == 500
392395

393-
assert_logs_contain_error(
394-
container.logs(), "'secret' not found. Please check available secrets."
395-
)
396+
assert_logs_contain_error(container.logs(), missing_secret_error_message)
396397
assert "Internal Server Error" in response.json()["error"]
397398

398399

truss/truss_config.py

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
class Accelerator(Enum):
4444
T4 = "T4"
45+
L4 = "L4"
4546
A10G = "A10G"
4647
V100 = "V100"
4748
A100 = "A100"

0 commit comments

Comments
 (0)