Set up Garnet in the AppHost
This article is the reference for the Aspire Garnet Hosting integration. It enumerates the AppHost APIs — with examples for both AppHost.cs and apphost.ts — that you use to model a Garnet resource in your AppHost project.
If you’re new to the Garnet integration, start with the Get started with Garnet integrations guide. For how consuming apps read the connection information this page exposes, see Connect to Garnet.
Installation
Section titled “Installation”To start building an Aspire app that uses Garnet, install the 📦 Aspire.Hosting.Garnet NuGet package:
aspire add garnetLearn more about aspire add in the command reference.
Or, choose a manual installation approach:
#:package Aspire.Hosting.Garnet@*<PackageReference Include="Aspire.Hosting.Garnet" Version="*" />aspire add garnetLearn more about aspire add in the command reference.
This updates your aspire.config.json with the Garnet hosting integration package:
{ "packages": { "Aspire.Hosting.Garnet": "13.3.0" }}Add Garnet resource
Section titled “Add Garnet resource”Once you’ve installed the hosting integration in your AppHost project, you can add a Garnet resource as shown in the following examples:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddGarnet("cache");
var exampleProject = builder.AddProject<Projects.ExampleProject>("apiservice") .WithReference(cache);
// After adding all resources, run the app...import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const cache = await builder.addGarnet("cache");
await builder.addNodeApp("api", "./api", "index.js") .withReference(cache);
// After adding all resources, run the app...-
When Aspire adds a container image to the AppHost, as shown in the preceding example with the
ghcr.io/microsoft/garnetimage, it creates a new Garnet instance on your local machine. -
The Garnet resource is configured with a randomly generated password by default. To set an explicit password, see Add Garnet resource with parameters.
-
The AppHost reference call configures a connection in the consuming project named after the referenced Garnet resource, such as
cachein the preceding example.
Add Garnet resource with data volume
Section titled “Add Garnet resource with data volume”Add a data volume to the Garnet resource as shown in the following examples:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddGarnet("cache") .WithDataVolume(isReadOnly: false);
var exampleProject = builder.AddProject<Projects.ExampleProject>() .WithReference(cache);
// After adding all resources, run the app...import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const cache = await builder.addGarnet("cache");await cache.withDataVolume({ isReadOnly: false });
await builder.addNodeApp("api", "./api", "index.js") .withReference(cache);
// After adding all resources, run the app...The data volume is used to persist Garnet data outside the lifecycle of its container. The data volume is mounted at the /data path in the Garnet container, and when a name parameter isn’t provided, the name is generated at random. Calling WithDataVolume (or withDataVolume) also enables Garnet persistence so the in-memory state survives container restarts. For more information on data volumes and details on why they’re preferred over bind mounts, see Docker docs: Volumes.
Add Garnet resource with data bind mount
Section titled “Add Garnet resource with data bind mount”Add a data bind mount to the Garnet resource as shown in the following examples:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddGarnet("cache") .WithDataBindMount( source: "/Garnet/Data", isReadOnly: false);
var exampleProject = builder.AddProject<Projects.ExampleProject>() .WithReference(cache);
// After adding all resources, run the app...import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const cache = await builder.addGarnet("cache");await cache.withDataBindMount("/Garnet/Data", { isReadOnly: false });
await builder.addNodeApp("api", "./api", "index.js") .withReference(cache);
// After adding all resources, run the app...Data bind mounts rely on the host machine’s filesystem to persist Garnet data across container restarts. The data bind mount is mounted at the C:\Garnet\Data on Windows (or /Garnet/Data on Unix) path on the host machine in the Garnet container. As with WithDataVolume, this call also enables persistence. For more information on data bind mounts, see Docker docs: Bind mounts.
Add Garnet resource with persistence
Section titled “Add Garnet resource with persistence”To configure Garnet snapshot persistence explicitly, call WithPersistence (or withPersistence) alongside a data volume or bind mount:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddGarnet("cache") .WithDataVolume() .WithPersistence( interval: TimeSpan.FromMinutes(5), keysChangedThreshold: 100);
var exampleProject = builder.AddProject<Projects.ExampleProject>() .WithReference(cache);
// After adding all resources, run the app...import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const cache = await builder.addGarnet("cache");await cache.withDataVolume();await cache.withPersistence({ interval: 5 * 60 * 1000,});
await builder.addNodeApp("api", "./api", "index.js") .withReference(cache);
// After adding all resources, run the app...The preceding code adds explicit persistence to the Garnet resource by snapshotting data at the configured interval. The C# AppHost accepts a TimeSpan for interval and a keysChangedThreshold to also trigger snapshots when a minimum number of keys change; the TypeScript AppHost accepts the interval as milliseconds.
Add Garnet resource with parameters
Section titled “Add Garnet resource with parameters”When you want to explicitly provide the port and password used by the Garnet container, you can pass them as parameters:
var builder = DistributedApplication.CreateBuilder(args);
var password = builder.AddParameter("password", secret: true);
var cache = builder.AddGarnet("cache", port: 6379, password: password);
var exampleProject = builder.AddProject<Projects.ExampleProject>() .WithReference(cache);
// After adding all resources, run the app...import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const password = await builder.addParameter("password", { secret: true });
const cache = await builder.addGarnet("cache", { port: 6379, password });
await builder.addNodeApp("api", "./api", "index.js") .withReference(cache);
// After adding all resources, run the app...When no password parameter is provided, Aspire generates a strong password automatically using the CreateDefaultPasswordParameter method.
Pass custom environment variables
Section titled “Pass custom environment variables”By default, Aspire injects the Garnet connection information using variable names derived from the resource name (for example, CACHE_URI, CACHE_HOST, CACHE_PORT, CACHE_PASSWORD). If your consuming app expects a different set of environment variable names, pass individual connection properties from the AppHost:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddGarnet("cache");
var app = builder.AddExecutable("my-app", "node", "app.js", ".") .WithReference(cache) .WithEnvironment(context => { context.EnvironmentVariables["GARNET_HOST"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Host); context.EnvironmentVariables["GARNET_PORT"] = cache.Resource.PrimaryEndpoint.Property(EndpointProperty.Port); context.EnvironmentVariables["GARNET_PASSWORD"] = cache.Resource.PasswordParameter; });
builder.Build().Run();import { createBuilder, EndpointProperty } from './.modules/aspire.js';
const builder = await createBuilder();
const cache = await builder.addGarnet("cache");const cacheEndpoint = await cache.getEndpoint("tcp");const cacheHost = await cacheEndpoint.property(EndpointProperty.Host);const cachePort = await cacheEndpoint.property(EndpointProperty.Port);
await builder.addNodeApp("my-app", "./app", "index.js") .withReference(cache) .withEnvironment("GARNET_HOST", cacheHost) .withEnvironment("GARNET_PORT", cachePort) .withEnvironment("GARNET_PASSWORD", await cache.passwordParameter());
await builder.build().run();Connect to an existing Garnet instance
Section titled “Connect to an existing Garnet instance”In C#, call AsExisting instead of AddGarnet to reference an externally managed Garnet instance:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddGarnet("cache") .AsExisting(connectionStringParameter: builder.AddParameter("cache-cs", secret: true));
var exampleProject = builder.AddProject<Projects.ExampleProject>() .WithReference(cache);
// After adding all resources, run the app...The TypeScript AppHost doesn’t currently expose an asExisting(...) API for Garnet. To connect to an existing Garnet instance from a TypeScript AppHost, use builder.addConnectionString(...) with a parameter and reference that connection string from your consuming apps instead.
Connection properties
Section titled “Connection properties”For the full reference of Garnet connection properties — and how consuming apps in C#, TypeScript, Python, and Go read them — see Connect to Garnet.
Hosting integration health checks
Section titled “Hosting integration health checks”The Garnet hosting integration automatically adds a health check for the Garnet resource. The health check verifies that the Garnet instance is running and that a connection can be established to it.
The hosting integration relies on the 📦 AspNetCore.HealthChecks.Redis NuGet package, which works for Garnet because it speaks the Redis serialization protocol.