feat(docker): Gracefully reload Caddy configuration
All checks were successful
Caddy Manager CI build / docker (push) Successful in 11m33s

This commit is contained in:
2026-07-26 11:39:59 +07:00
parent 284036b549
commit d0687c9134
10 changed files with 200 additions and 22 deletions

View File

@@ -15,12 +15,8 @@ public class DockerService(IConfigurationsService configurationsService) : IDock
/// Method to get the container id of the Caddy container by the name configured
/// </summary>
/// <returns></returns>
private async Task<string> GetCaddyContainerId()
private async Task<string> GetCaddyContainerId(IDockerClient client)
{
var client = new DockerClientConfiguration(new Uri(Configuration.DockerHostWithEnvCheck)).CreateClient();
if (client == null) return string.Empty;
var containers = await client.Containers.ListContainersAsync(new ContainersListParameters
{
All = true
@@ -30,19 +26,75 @@ public class DockerService(IConfigurationsService configurationsService) : IDock
?.ID ?? string.Empty;
}
private IDockerClient CreateClient() =>
new DockerClientConfiguration(new Uri(Configuration.DockerHostWithEnvCheck)).CreateClient();
/// <inheritdoc />
public async Task RestartCaddyContainerAsync()
{
var containerId = await GetCaddyContainerId();
if (string.IsNullOrEmpty(containerId)) return;
var client = new DockerClientConfiguration(new Uri(Configuration.DockerHostWithEnvCheck)).CreateClient();
using var client = CreateClient();
if (client != null)
var containerId = await GetCaddyContainerId(client);
if (string.IsNullOrEmpty(containerId)) return;
await client.Containers.RestartContainerAsync(containerId, new ContainerRestartParameters());
}
/// <inheritdoc />
public async Task<CaddyReloadResponse> ReloadCaddyContainerAsync()
{
try
{
await client.Containers.RestartContainerAsync(containerId, new ContainerRestartParameters());
using var client = CreateClient();
var containerId = await GetCaddyContainerId(client);
if (string.IsNullOrEmpty(containerId))
{
return new CaddyReloadResponse
{
Message = $"Caddy container '{Configuration.CaddyContainerName}' was not found"
};
}
var exec = await client.Exec.ExecCreateContainerAsync(containerId, new ContainerExecCreateParameters
{
Cmd = ["caddy", "reload", "--config", Configuration.CaddyConfigPathInContainer],
AttachStdout = true,
AttachStderr = true
});
string stdout, stderr;
using (var stream = await client.Exec.StartAndAttachContainerExecAsync(exec.ID, false))
{
(stdout, stderr) = await stream.ReadOutputToEndAsync(CancellationToken.None);
}
var inspection = await client.Exec.InspectContainerExecAsync(exec.ID);
if (inspection.ExitCode == 0)
{
return new CaddyReloadResponse { Success = true };
}
// Caddy reports errors on stderr, interleaved with its structured JSON progress logs which are noise here
var output = string.Join(Environment.NewLine, $"{stderr}{Environment.NewLine}{stdout}"
.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Where(line => !line.StartsWith('{')));
return new CaddyReloadResponse
{
Message = string.IsNullOrWhiteSpace(output)
? $"Caddy reload failed with exit code {inspection.ExitCode}"
: output.Trim()
};
}
catch (Exception e)
{
return new CaddyReloadResponse { Message = e.Message };
}
}
}