-
Notifications
You must be signed in to change notification settings - Fork 746
Description
Is there an existing issue for this?
- I have searched the existing issues
Is your feature request related to a problem? Please describe the problem.
Feature Request: Add SQL Commander (WithSqlCommander()) to Aspire SQL Server Hosting
Issue Type
✨ Feature Request
Area
area-integrations – Issues pertaining to Aspire Integrations packages
Summary
Add native support for SQL Commander, a lightweight web-based SQL Server management tool, to the Aspire.Hosting.SqlServer package via a WithSqlCommander() extension method on SqlServerDatabaseResource. This would give SQL Server developers the same first-class database exploration experience that PostgreSQL and MySQL developers enjoy with WithPgAdmin(), WithPgWeb(), and WithPhpMyAdmin().
Motivation
Current Gap
SQL Server is the only major database in Aspire that lacks a built-in web UI management tool:
- ✅ PostgreSQL has
WithPgAdmin()andWithPgWeb() - ✅ MySQL has
WithPhpMyAdmin() - ✅ MongoDB has
WithMongoExpress() - ❌ SQL Server has no built-in web admin UI
This creates an inconsistent developer experience and forces SQL Server developers to:
- Manually copy connection strings from the Aspire dashboard
- Parse server, database, username, and password manually
- Open external tools like SSMS or VS Code with the mssql extension
- Repeatedly switch between IDE and database tool during debugging
Why SQL Commander?
SQL Commander is purpose-built for the Aspire development workflow.
Lightweight & Cloud-Native
- Single-page web interface (no local installation required)
- Instant startup, no sign-in required
- Optimized for quick database exploration during development
- Supports traditional SQL auth (username/password)
- Supports Azure Default Credential (passwordless) for Azure SQL and SQL Server in Azure
- Works seamlessly in local dev and Azure environments
Perfect for Debugging
- Browse tables, views, stored procedures quickly
- Execute ad-hoc queries with real-time feedback
- Generate CREATE, SELECT, and DROP scripts
- Export metadata as JSON for documentation or tooling
- Light and dark mode support
- VS Code integration (builds a
vscode://ms-mssql.mssql/connectlink)
Production-Safe
- Intended for development and debugging only
- Should be excluded from production manifests (similar to pgAdmin/phpMyAdmin)
- No persistent state or configuration required (unless explicitly mounted)
- Runs as a non-root user in the container
- Exposes a health endpoint for orchestration
Proposed API
Following the established pattern from WithPgAdmin() and WithPhpMyAdmin():
public static IResourceBuilder<SqlServerDatabaseResource> WithSqlCommander(
this IResourceBuilder<SqlServerDatabaseResource> builder,
Action<IResourceBuilder<SqlCommanderContainerResource>>? configureContainer = null,
string? containerName = null)Note: Targeting
SqlServerDatabaseResourcelets the tool bind naturally to a specific database, while still being able to infer server information from the parentSqlServerServerResource.
Usage Example
var builder = DistributedApplication.CreateBuilder(args);
var sql = builder.AddSqlServer("sql");
var db = sql
.AddDatabase("mydb")
.WithSqlCommander(); // 👈 New extension method
builder.Build().Run();Advanced Configuration
var db = builder
.AddSqlServer("sql")
.AddDatabase("mydb")
.WithSqlCommander(configureContainer: container =>
{
container.WithHostPort(9000); // Custom host port
container.WithEnvironment("SQLCMDR_FILE_LOG", "1"); // Enable file logging
});Multiple Databases / Instances
Today, SQL Commander is designed as one container per database. Each call to WithSqlCommander() would result in a separate container instance that is bound to that specific SqlServerDatabaseResource.
var sql = builder.AddSqlServer("sql");
// Each database gets its own SQL Commander container
var db1 = sql.AddDatabase("db1").WithSqlCommander(); // sqlcmdr-db1
var db2 = sql.AddDatabase("db2").WithSqlCommander(); // sqlcmdr-db2
// Or multiple SQL Server instances
var sql1 = builder.AddSqlServer("sql1");
var db3 = sql1.AddDatabase("db3").WithSqlCommander();
var sql2 = builder.AddSqlServer("sql2");
var db4 = sql2.AddDatabase("db4").WithSqlCommander();This keeps the implementation simple and makes the binding between a given SQL Commander instance and a single database explicit. A future enhancement could optionally add a multi-database mode (e.g., one container with a database selector UI), but that is not required for an initial implementation.
Container Information
Registry: Docker Hub
Image: jerrynixon/sql-commander
Tag: latest (semantic version tags like 1.1.0 also available)
Port: 8080 (HTTP)
Base Image: mcr.microsoft.com/dotnet/aspnet:8.0
License: MIT
Container Configuration
Environment Variables:
ConnectionStrings__db– SQL Server connection string (to be auto-configured by Aspire)ASPNETCORE_URLS– Default:http://+:8080SQLCMDR_FILE_LOG– Optional: set to1to enable file logging (disabled by default)
Health Check:
- Endpoint:
GET /health - Response:
{ "status": "ok" }
Security:
- Runs as non-root user (
appuser) - No secrets baked into the image
- Connection strings must be provided at runtime
- Stateless design; persistence is opt-in via volume mounts
Implementation Approach
The implementation can closely follow the existing WithPhpMyAdmin() and WithPgAdmin() patterns, adapted for SQL Server and database resources:
-
Per-Database Container Pattern (Initial Version)
Keep the initial implementation simple and predictable by creating oneSqlCommanderContainerResourceperSqlServerDatabaseResource. This mirrors how SQL Commander is typically used today (one site bound to one database) and avoids the complexity of multi-database configuration and UI routing for a first iteration. -
Connection Configuration
ConfigureConnectionStrings__dbvia environment variables using Aspire’s parameter system, including:- Server host and port from the parent
SqlServerServerResourceprimary endpoint - Database name from the
SqlServerDatabaseResource - Credentials from the SQL Server resource (or rely on Azure identity where appropriate)
- Server host and port from the parent
-
Event-Driven Setup
Subscribe toBeforeResourceStartedEventfor theSqlCommanderContainerResourceto:- Discover
SqlServerDatabaseResource(and their parents) - Generate appropriate connection strings
- Optionally write config files if multi-database support is desired
- Discover
-
Automatic Exclusion from Deployment
Use.ExcludeFromManifest()so SQL Commander is only used in local dev / orchestration scenarios and not deployed to production by default. -
Health Integration
Use.WithHttpHealthCheck("/health")so Aspire waits for SQL Commander to be ready and can surface health in the dashboard.
Key Types
New Resource Type
public class SqlCommanderContainerResource : ContainerResource
{
public SqlCommanderContainerResource(string name) : base(name) { }
}Host Port Helper (following the pgAdmin/phpMyAdmin pattern)
public static IResourceBuilder<SqlCommanderContainerResource> WithHostPort(
this IResourceBuilder<SqlCommanderContainerResource> builder,
int? port)
{
ArgumentNullException.ThrowIfNull(builder);
return builder.WithEndpoint("http", endpoint =>
{
endpoint.Port = port;
});
}Connection String Format (Example)
For SQL auth:
Server={endpoint.Resource.Name},{endpoint.TargetPort};
Database={databaseName};
User Id={userName};
Password={password};
TrustServerCertificate=True
For Azure Default Credential:
Server={endpoint.Resource.Name},{endpoint.TargetPort};
Database={databaseName};
// No credentials in the connection string – SQL Commander uses Azure.Identity
(Exact behavior can align with how SQL Commander already handles Azure Default Credential.)
Benefits
For Developers
- Consistent Experience: SQL Server developers get parity with PostgreSQL and MySQL.
- Faster Debugging: No manual copying/parsing of connection strings.
- Zero Extra Setup: Works out of the box once
.WithSqlCommander()is called. - Modern Workflow: Web-based, accessible from the Aspire dashboard.
- VS Code Integration: “Open in VS Code” support via the mssql extension.
For Aspire
- Feature Parity: Fills the SQL Server tooling gap highlighted in issue Add admin interface or integration for SqlServer containers similar to PgAdmin/PgWeb/MongoExpress #7742.
- Consistent API: Mirrors
WithPgAdmin(),WithPgWeb(), andWithPhpMyAdmin(). - Production-Safe: Excluded from manifests so it isn’t accidentally deployed.
For the Ecosystem
- First-Class SQL Server Support for cloud-native .NET apps.
- Azure-Ready via Azure Default Credential support.
- Clear Example for future database management tooling integrations.
Real-World Usage
SQL Commander is already used alongside Aspire, but wired up manually:
// Current manual approach (works, but not ideal)
var sql = builder.AddSqlServer("sql");
var db = sql.AddDatabase("mydb");
var sqlcmdr = builder
.AddProject<Projects.SqlCmdr_Web>("sqlcmdr")
.WithReference(db);Native support would simplify this to:
// Proposed approach
var db = builder
.AddSqlServer("sql")
.AddDatabase("mydb")
.WithSqlCommander();Related Issues
- Add admin interface or integration for SqlServer containers similar to PgAdmin/PgWeb/MongoExpress #7742 – Add admin interface or integration for SqlServer containers similar to PgAdmin/PgWeb/MongoExpress (currently considered covered via CommunityToolkit DbGate, but this would provide a native, SQL Server–focused option).
Documentation
- SQL Commander GitHub: https://github.com/JerryNixon/sql-commander
- SQL Commander Docker Hub: https://hub.docker.com/r/jerrynixon/sql-commander
This feature request addresses a real gap in the Aspire developer experience and provides SQL Server developers with the same convenience that developers of other database platforms already enjoy. The proposal follows proven patterns from existing Aspire integrations and should require minimal, well-scoped changes to the Aspire.Hosting.SqlServer package and its related types.
Describe the solution you'd like
See above
Additional context
See above