Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ builder.AddLocalStack(configureContainer: container =>
// Optional: Enable verbose logging for troubleshooting
container.DebugLevel = 1;
container.LogLevel = LocalStackLogLevel.Debug;

// Optional: Use a specific port instead of dynamic port assignment
container.Port = 4566;
});
```

Expand All @@ -103,6 +106,7 @@ builder.AddLocalStack(configureContainer: container =>
- **`Lifetime`** - Container lifecycle: `Persistent` (survives restarts) or `Session` (cleaned up on stop)
- **`DebugLevel`** - LocalStack debug verbosity (0 = default, 1 = verbose)
- **`LogLevel`** - Log level control (Error, Warn, Info, Debug, Trace, etc.)
- **`Port`** - Static port mapping for LocalStack container. If set, LocalStack will be mapped to this static port on the host. If not set, a dynamic port will be used unless the container lifetime is persistent, in which case the default LocalStack port (4566) is used. Useful for avoiding port conflicts or for predictable endpoint URLs
- **`AdditionalEnvironmentVariables`** - Custom environment variables for advanced scenarios

For detailed configuration guide and best practices, see [Configuration Documentation](docs/CONFIGURATION.md).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,13 @@ public sealed class LocalStackContainerOptions
/// Default: false
/// </remarks>
public bool EnableDockerSocket { get; set; }

/// <summary>
/// Gets or sets the port to expose LocalStack on the host machine.
/// </summary>
/// <remarks>
/// If set, LocalStack will be mapped to this static port on the host. If not set, a dynamic port will be used unless the container lifetime is persistent,
/// in which case the default LocalStack port is used. Useful for avoiding port conflicts or for predictable endpoint URLs.
/// </remarks>
public int? Port { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,10 @@ public static IDistributedApplicationBuilder UseLocalStack(this IDistributedAppl
.WithImage(LocalStackContainerImageTags.Image)
.WithImageRegistry(LocalStackContainerImageTags.Registry)
.WithImageTag(LocalStackContainerImageTags.Tag)
.WithHttpEndpoint(targetPort: Constants.DefaultContainerPort, name: LocalStackResource.PrimaryEndpointName)
.WithHttpEndpoint(targetPort: Constants.DefaultContainerPort,
// Map to a static port if specified or if using a persistent lifetime; otherwise, use dynamic port mapping
port: containerOptions.Port ?? (containerOptions.Lifetime == ContainerLifetime.Persistent ? Constants.DefaultContainerPort : null),
name: LocalStackResource.PrimaryEndpointName)
.WithLifetime(containerOptions.Lifetime)
.WithEnvironment("DEBUG", containerOptions.DebugLevel.ToString(CultureInfo.InvariantCulture))
.WithEnvironment("LS_LOG", containerOptions.LogLevel.ToEnvironmentValue())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,23 @@ public void EnableDockerSocket_Should_Be_Settable()

Assert.True(options.EnableDockerSocket);
}

[Fact]
public void Port_Should_Default_To_Null()
{
var options = new LocalStackContainerOptions();

Assert.Null(options.Port);
}

[Fact]
public void Port_Should_Be_Settable()
{
var options = new LocalStackContainerOptions
{
Port = 1234,
};

Assert.Equal(1234, options.Port);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -288,4 +288,35 @@ public void AddLocalStack_Should_Not_Mount_Docker_Socket_By_Default()

Assert.Null(dockerSocketMount);
}

[Theory]
[InlineData(ContainerLifetime.Session, null, null)]
[InlineData(ContainerLifetime.Session, 1234, 1234)]
[InlineData(ContainerLifetime.Persistent, null, Constants.DefaultContainerPort)]
[InlineData(ContainerLifetime.Persistent, 1234, 1234)]
public void AddLocalStack_Should_Set_Endpoint_Port(ContainerLifetime lifetime, int? port, int? expectedPort)
{
var builder = DistributedApplication.CreateBuilder([]);
var (localStackOptions, _, _) = TestDataBuilders.CreateMockLocalStackOptions(useLocalStack: true);

var result = builder.AddLocalStack
(
localStackOptions: localStackOptions,
configureContainer: container =>
{
container.Lifetime = lifetime;
container.Port = port;
});

Assert.NotNull(result);
var resource = result.Resource;
Assert.NotNull(resource);

// Verify endpoint port configuration
var endpointAnnotations = resource.Annotations.OfType<EndpointAnnotation>();
var httpEndpoint = endpointAnnotations.FirstOrDefault(e => e is { Name: "http" });

Assert.NotNull(httpEndpoint);
Assert.Equal(expectedPort, httpEndpoint.Port);
}
}
Loading