diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 463ddcdc9..e2650d7f7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -6,6 +6,9 @@ "version": "10.28.0" } }, + "containerEnv": { + "ASTRO_TELEMETRY_DISABLED": "1" + }, "customizations": { "codespaces": { "openFiles": [ diff --git a/src/frontend/config/sidebar/docs.topics.ts b/src/frontend/config/sidebar/docs.topics.ts index 252aad6fe..048fc3dde 100644 --- a/src/frontend/config/sidebar/docs.topics.ts +++ b/src/frontend/config/sidebar/docs.topics.ts @@ -624,6 +624,27 @@ export const docsTopics: StarlightSidebarTopicsUserConfig = { }, slug: 'fundamentals/service-discovery', }, + { + label: 'Environment variables', + slug: 'fundamentals/environment-variables', + translations: { + da: 'Miljøvariabler', + de: 'Umgebungsvariablen', + en: 'Environment variables', + es: 'Variables de entorno', + fr: "Variables d'environnement", + hi: 'पर्यावरण चर', + id: 'Variabel lingkungan', + it: 'Variabili di ambiente', + ja: '環境変数', + ko: '환경 변수', + 'pt-BR': 'Variáveis de ambiente', + ru: 'Переменные среды', + tr: 'Ortam değişkenleri', + uk: 'Змінні середовища', + 'zh-CN': '环境变量', + }, + }, { label: 'Networking overview', slug: 'fundamentals/networking-overview', diff --git a/src/frontend/src/content/docs/fundamentals/environment-variables.mdx b/src/frontend/src/content/docs/fundamentals/environment-variables.mdx new file mode 100644 index 000000000..aa92c1dea --- /dev/null +++ b/src/frontend/src/content/docs/fundamentals/environment-variables.mdx @@ -0,0 +1,219 @@ +--- +title: Environment variables +seoTitle: Aspire environment variable naming conventions guide +description: Learn how Aspire generates environment variable names for connection strings, endpoints, service discovery, and resource properties. +--- + +import { Aside } from '@astrojs/starlight/components'; + +When you use `WithReference` to connect resources in the AppHost, Aspire automatically injects environment variables into the consuming resource. This process is called _configuration injection_. + +These environment variable names follow specific conventions based on the referenced resource's name and type. Understanding the conventions is especially useful for applications that read environment variables directly instead of relying on typed Aspire client integrations. + +## Naming conventions + +Aspire generates environment variables in different formats depending on the type of resource being referenced. The following sections describe each category. + +### Connection strings + +When you reference a resource that exposes a connection string (such as a database, cache, or messaging resource), Aspire generates an environment variable using the `ConnectionStrings__` prefix: + +```txt +ConnectionStrings__{resource-name} +``` + +The resource name is used **as-is** (preserving the original casing and hyphens). For example: + +```csharp title="C# — AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var cache = builder.AddRedis("my-cache"); +var db = builder.AddPostgres("postgres").AddDatabase("my-db"); + +var api = builder.AddProject("api") + .WithReference(cache) + .WithReference(db); + +// After adding all resources, run the app... +builder.Build().Run(); +``` + +The `api` resource receives the following environment variables: + +| Environment variable | Description | +| ----------------------------- | --------------------------------------------- | +| `ConnectionStrings__my-cache` | Connection string for the Redis cache | +| `ConnectionStrings__my-db` | Connection string for the PostgreSQL database | + + + +### Endpoint URLs + +When you reference a resource that exposes endpoints (such as a project or container service), Aspire generates an environment variable for each endpoint. The resource name and endpoint name are **encoded** (hyphens and other non-alphanumeric characters are replaced with underscores), then **uppercased**: + +```txt +{RESOURCE_NAME}_{ENDPOINT_NAME} +``` + +For example: + +```csharp title="C# — AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var api = builder.AddProject("my-api"); + +var frontend = builder.AddJavaScriptApp("frontend", "./app") + .WithReference(api); + +// After adding all resources, run the app... +builder.Build().Run(); +``` + +The `frontend` resource receives: + +| Environment variable | Example value | +| -------------------- | ------------------------ | +| `MY_API_HTTP` | `http://localhost:5000` | +| `MY_API_HTTPS` | `https://localhost:5001` | + +The suffix comes from the endpoint name, not necessarily its URI scheme. For example, a named endpoint called `admin` on `my-api` produces `MY_API_ADMIN`. For resource endpoints, Aspire retains the endpoint suffix even when the resource exposes only one endpoint. + +### Service discovery variables + +Aspire also generates service discovery variables for .NET service resolution. These use the format: + +```txt +services__{resource-name}__{endpoint-key}__{index} +``` + +The `services` prefix and double-underscore (`__`) separators are fixed, but the resource name preserves the casing used in the AppHost. For example, `AddProject("MyApi")` with an HTTP endpoint produces `services__MyApi__http__0`. The endpoint key is the scheme for endpoints named `http` or `https`; otherwise, Aspire uses the endpoint name. Applications that don't use .NET service discovery can read the [endpoint URL variables](#endpoint-urls) instead. + +### Resource properties + +Some integrations expose individual resource properties as environment variables. The resource name is **encoded** (hyphens replaced with underscores) and **uppercased**, with the property name appended: + +```txt +{RESOURCE_NAME}_{PROPERTY} +``` + +For example, a ClickHouse resource named `my-clickhouse` exposes: + +| Environment variable | Description | +| ---------------------------- | ----------------- | +| `MY_CLICKHOUSE_HOST` | The hostname | +| `MY_CLICKHOUSE_PORT` | The port number | +| `MY_CLICKHOUSE_USERNAME` | The username | +| `MY_CLICKHOUSE_PASSWORD` | The password | +| `MY_CLICKHOUSE_DATABASENAME` | The database name | + +## Resource name encoding rules + +When a resource name is used in an endpoint URL or property variable, Aspire applies the following transformations: + +1. **Unsupported characters are replaced with underscores**: Hyphens (`-`), dots (`.`), and any other characters that aren't ASCII letters, digits, or underscores are replaced with `_`. +2. **Leading digits get a prefix**: If the name starts with a digit, an underscore (`_`) is prepended. +3. **The result is uppercased**: The encoded name is converted to uppercase for the final environment variable name. + +For example, a resource named `foundry-demo-proj` becomes `FOUNDRY_DEMO_PROJ` in environment variable prefixes: + +| Resource name | Encoded prefix | Example variable | +| ------------------- | ------------------- | ----------------------- | +| `api` | `API` | `API_HTTP` | +| `my-api` | `MY_API` | `MY_API_HTTPS` | +| `foundry-demo-proj` | `FOUNDRY_DEMO_PROJ` | `FOUNDRY_DEMO_PROJ_URI` | + + + +## Accessing environment variables + +### C\# + +In .NET applications, Aspire client integrations handle environment variable access automatically. For manual access: + +```csharp title="C# — Program.cs" +// Connection strings +string cache = builder.Configuration.GetConnectionString("my-cache"); + +// Endpoint URLs +string apiUrl = builder.Configuration.GetValue("MY_API_HTTP"); + +// Resource properties +string host = builder.Configuration.GetValue("MY_CLICKHOUSE_HOST"); +``` + +### Python + +```python title="Python — main.py" +import os + +# Connection strings +cache_conn = os.getenv("ConnectionStrings__my-cache") + +# Endpoint URLs +api_url = os.getenv("MY_API_HTTP") + +# Resource properties +db_host = os.getenv("MY_CLICKHOUSE_HOST") +``` + +### JavaScript / TypeScript + +```javascript title="JavaScript — app.js" +// Connection strings (use bracket notation for names with hyphens) +const cacheConn = process.env['ConnectionStrings__my-cache']; + +// Endpoint URLs +const apiUrl = process.env.MY_API_HTTP; + +// Resource properties +const dbHost = process.env.MY_CLICKHOUSE_HOST; +``` + + + +## Custom environment variables + +If you need different variable names, use `WithEnvironment` to set custom environment variables: + +```csharp title="C# — AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var db = builder.AddPostgres("postgres").AddDatabase("my-db"); + +var api = builder.AddPythonApp("api", "../api", "main.py") + .WithReference(db) + .WithEnvironment("DB_HOST", db.Resource.Parent.PrimaryEndpoint.Property(EndpointProperty.Host)) + .WithEnvironment("DB_PORT", db.Resource.Parent.PrimaryEndpoint.Property(EndpointProperty.Port)); + +// After adding all resources, run the app... +builder.Build().Run(); +``` + +This approach lets you define explicit, predictable variable names without relying on the automatic naming conventions. + + + +## See also + +- [Service discovery](/fundamentals/service-discovery/) +- [Inner-loop networking overview](/fundamentals/networking-overview/) +- [Python integration](/integrations/frameworks/python/) +- [JavaScript integration](/integrations/frameworks/javascript/) +- [Executable resources](/app-host/executable-resources/) +- [Legacy deployment manifest format](/deployment/azure/manifest-format/) diff --git a/src/frontend/src/content/docs/fundamentals/service-discovery.mdx b/src/frontend/src/content/docs/fundamentals/service-discovery.mdx index f28a1727b..f44376910 100644 --- a/src/frontend/src/content/docs/fundamentals/service-discovery.mdx +++ b/src/frontend/src/content/docs/fundamentals/service-discovery.mdx @@ -85,6 +85,10 @@ In the preceding example, the _frontend_ project references the _catalog_ projec their explicit dependencies. +:::tip +For the environment variable formats generated by `WithReference`, including endpoint and service discovery variables, see [Environment variables](/fundamentals/environment-variables/). +::: + ## Named endpoints Some services expose multiple, named endpoints. Named endpoints can be resolved by specifying the endpoint name in the host portion of the HTTP request URI, following the format `scheme://_endpointName.serviceName`. For example, if a service named "basket" exposes an endpoint named "dashboard", then the URI `https+http://_dashboard.basket` can be used to specify this endpoint, for example: diff --git a/src/frontend/src/content/docs/integrations/frameworks/javascript.mdx b/src/frontend/src/content/docs/integrations/frameworks/javascript.mdx index 930a1008b..b9c7d71f0 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/javascript.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/javascript.mdx @@ -986,6 +986,57 @@ Common environment variables for JavaScript frameworks: - **VITE_PORT**: For Vite applications - **HOST**: Some frameworks also use this to bind to specific interfaces +### Read referenced connection strings + +When you reference a resource that exposes a connection string, Aspire injects the connection string into the JavaScript app's environment: + + + + +```csharp title="AppHost.cs" +var builder = DistributedApplication.CreateBuilder(args); + +var db = builder.AddPostgres("postgres").AddDatabase("mydb"); + +var app = builder.AddJavaScriptApp("app", "./app") + .WithHttpEndpoint(port: 3000, env: "PORT") + .WithReference(db); + +// After adding all resources, run the app... +builder.Build().Run(); +``` + + + + +```typescript title="apphost.mts" +import { createBuilder } from './.aspire/modules/aspire.mjs'; + +const builder = await createBuilder(); + +const postgres = await builder.addPostgres('postgres'); +const db = await postgres.addDatabase('mydb'); + +const app = await builder + .addJavaScriptApp('app', './app') + .withHttpEndpoint({ port: 3000, env: 'PORT' }); +await app.withReference(db); + +// After adding all resources, run the app... +await builder.build().run(); +``` + + + + +Read the connection string in your JavaScript code: + +```javascript title="app.js" +const connectionString = process.env.ConnectionStrings__mydb; +``` + +For details about how resource names map to environment variable names, see [Environment variables](/fundamentals/environment-variables/). + ## Customize Vite configuration For Vite applications, you can specify a custom configuration file if you need to override the default Vite configuration resolution behavior: @@ -1427,6 +1478,7 @@ configuration, configure the production-serving resource separately. ## See also +- [Environment variables](/fundamentals/environment-variables/) - How Aspire generates environment variable names from resources - [External parameters](/fundamentals/external-parameters/) - Learn how to use parameters in Aspire - [JavaScript monorepo hosting extensions](/integrations/frameworks/nodejs-extensions/) - Community Toolkit extensions for Nx and Turborepo workspaces - [Deploy JavaScript apps](/deployment/javascript-apps/) - Production deployment patterns including `PublishAsStaticWebsite`, `PublishAsNodeServer`, and `PublishAsPackageScript` diff --git a/src/frontend/src/content/docs/integrations/frameworks/python.mdx b/src/frontend/src/content/docs/integrations/frameworks/python.mdx index e0981a5eb..21908b347 100644 --- a/src/frontend/src/content/docs/integrations/frameworks/python.mdx +++ b/src/frontend/src/content/docs/integrations/frameworks/python.mdx @@ -621,6 +621,8 @@ import os connection_string = os.environ.get("ConnectionStrings__mydb") ``` +For details about how resource names map to environment variable names, see [Environment variables](/fundamentals/environment-variables/). + ## HTTPS configuration By default, Python apps run over HTTP in local development. To enable HTTPS, use `WithHttpsEndpoint` together with `WithHttpsDeveloperCertificate`: @@ -786,6 +788,7 @@ The generated Dockerfile is tailored to your detected Python version and depende ## See also +- [Environment variables](/fundamentals/environment-variables/) - How Aspire generates environment variable names from resources - [📦 Aspire.Hosting.Python NuGet package](https://www.nuget.org/packages/Aspire.Hosting.Python) - [Python language reference](https://docs.python.org/3/) - [Uvicorn documentation](https://www.uvicorn.org/)