Skip to content

[BUG] Shipped appsettings.json has a Docker instance with an empty Name, so the default config fails startup #288

Open

Description

@LarsLaskowski

Summary

The appsettings.json shipped in the image defines one Docker instance whose Name is an empty string. Configuration validation rejects an instance without a name, so the application refuses to start with its own default configuration unless the operator overrides the name (the compose files do, other setups do not). The shipped defaults should pass validation as soon as the operator supplies the database connection string.

Area

Current behavior

  • src/DockerUpdateGuard/appsettings.json:51-70:
"DockerInstances": [
  {
    "Name": "",
    "BaseUrl": "unix:///var/run/docker.sock",
    "Enabled": true,
    ...
  • src/DockerUpdateGuard/Configuration/DockerUpdateGuardOptionsValidator.cs:276-281:
if (string.IsNullOrWhiteSpace(instance.Name))
{
    failures.Add($"'{DockerUpdateGuardOptions.SectionName}:DockerInstances:Name' must be configured");
    continue;
}
  • Options are validated at startup (ServiceCollectionExtensions.cs:53-56, ValidateOnStart()), and any violation fails startup.
  • The compose files set the name explicitly (docs/docker-compose.minimal.yml:42, docs/docker-compose.trivy.yml:52, docs/docker-compose.full.yml:65: DockerUpdateGuard__DockerInstances__0__Name: "Local Docker"), which hides the problem there. The README recommends Local Docker as the name (README.md:175) but documents Name as "default none, required" (README.md:163).

Reproduction: run the image with only the connection string supplied, e.g. -e ConnectionStrings__DockerUpdateGuard="Host=db;Database=dug;Username=dug;Password=…" and the Docker socket mounted, without DockerUpdateGuard__DockerInstances__0__Name. Startup fails with 'DockerUpdateGuard:DockerInstances:Name' must be configured. The same happens when an operator layers an appsettings.Production.json that does not repeat the instance name, or sets only DockerUpdateGuard__DockerInstances__0__BaseUrl.

Expected behavior

  • The shipped appsettings.json passes DockerUpdateGuardOptionsValidator once a connection string is supplied (the connection string itself stays deliberately empty — the operator must provide the database).
  • The shipped instance is named Local Docker (the name the README and all compose files already use), keeps BaseUrl unix:///var/run/docker.sock and Enabled: true, so the documented environment-variable overrides at index 0 keep working unchanged.
  • Validation rules stay as they are (an explicitly empty name is still rejected).

Acceptance criteria

  • src/DockerUpdateGuard/appsettings.json sets DockerInstances[0].Name to Local Docker.
  • Unit test that loads the shipped appsettings.json from the host project (same approach as TelemetryServiceCollectionExtensionsConfigurationSamplesUseCurrentTelemetrySchema in src/Tests/DockerUpdateGuard.Tests/TelemetryServiceCollectionExtensionsTests.cs, using its GetHostProjectPath() pattern), adds a connection string in memory, binds DockerUpdateGuardOptions and asserts that DockerUpdateGuardOptionsValidator succeeds — e.g. DockerUpdateGuardOptionsValidatorShippedAppSettingsWithConnectionStringSucceeds in DockerUpdateGuardOptionsValidatorTests.cs. Assertion message lists the failures if any.
  • Existing compose files keep working (they override the same name; no change required, optional cleanup only).
  • README configuration reference: DockerInstances[0] defaults reflect the shipped instance (Local Docker, unix:///var/run/docker.sock).
  • The area documents docs/areas/docker-instances.md and docs/areas/hosting.md describe the shipped default instance, and the statement/Known gaps entry about the empty shipped name is removed.

Implementation notes

  • One-line configuration change plus the regression test; no code change in the validator.
  • Pitfall: configuration arrays merge by index across sources. Keeping exactly one shipped instance at index 0 preserves the current override behavior (DockerUpdateGuard__DockerInstances__0__…). An alternative — shipping an empty DockerInstances array — was considered and rejected: it would silently remove the default socket instance for setups that only override Name, and the compose files would have to set every key.
  • Renaming affects nothing stored: instances are identified by trimmed name, and an instance with an empty name was never able to start.
  • Must not change: validation messages, the empty shipped connection string, the guarantee that configuration errors fail startup.
  • No migration.

Related


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions