mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 07:41:27 +00:00
fix: HA checks resolve service targets over project network; persist checks (#13)
CI / Infra (Compose + Scripts) (push) Canceled after 0s
CI / Backend (Go) (push) Canceled after 0s
CI / Frontend (React) (push) Canceled after 0s
CI / Compose boot smoke (push) Canceled after 0s
CI / Build & publish images (push) Canceled after 0s
CI / Release (push) Canceled after 0s
CI / Infra (Compose + Scripts) (push) Canceled after 0s
CI / Backend (Go) (push) Canceled after 0s
CI / Frontend (React) (push) Canceled after 0s
CI / Compose boot smoke (push) Canceled after 0s
CI / Build & publish images (push) Canceled after 0s
CI / Release (push) Canceled after 0s
- Health checks for local services dialed 127.0.0.1 from inside the backend
container — the host's published port is unreachable there. Service-bound
checks now resolve the service's DNS name on its project network (backend
joins on demand), falling back to the service's stored port. A resolver
failure surfaces as TARGET_UNRESOLVED instead of a fake loopback probe.
- Checks lived only in memory: a backend restart silently deleted every
configured health check. ha_health_checks table + write-through on
add/update/tick and hydrate-on-boot, matching the scaling-policy pattern.
- sqlc schema.sql gained the runtime columns added by later migrations —
the stale snapshot already caused one silently-dropped-column bug.
- OpenAPI: runtime response now documents ports and health fields; types
regenerated.
- Buttons no longer wrap ("+ new project" rendered on two lines).
Verified live: service check probes whoami-web:80 via DNS → healthy;
check survives a backend restart and rehydrates.
Generated with [Devin](https://devin.ai)
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
32b52d121f
commit
15b5b0e6e7
8 files changed
+216
-21
No files matched your search
@@ -67,7 +67,9 @@ type RuntimeState struct {
|
||||
Status string `json:"status"` // running, degraded, stopped
|
||||
}
|
||||
|
||||
func projectNetworkName(projectID string) string {
|
||||
// ProjectNetworkName is the deterministic docker network every service in a
|
||||
// project joins — containr-proj-<first 12 hex chars of the project uuid>.
|
||||
func ProjectNetworkName(projectID string) string {
|
||||
short := strings.ReplaceAll(projectID, "-", "")
|
||||
if len(short) > 12 {
|
||||
short = short[:12]
|
||||
@@ -82,7 +84,7 @@ func serviceNamePrefix(serviceID string) string {
|
||||
// EnsureProjectNetwork creates the per-project bridge network if missing.
|
||||
// Containers on it resolve each other by service name (private networking).
|
||||
func (de *DeploymentEngine) EnsureProjectNetwork(ctx context.Context, projectID string) (string, error) {
|
||||
name := projectNetworkName(projectID)
|
||||
name := ProjectNetworkName(projectID)
|
||||
|
||||
networks, err := de.dockerClient.ListNetworks(ctx)
|
||||
if err != nil {
|
||||
@@ -364,7 +366,7 @@ func (de *DeploymentEngine) ProbeServiceHealth(ctx context.Context, state *Runti
|
||||
}
|
||||
|
||||
probeURL := ""
|
||||
if networkName := projectNetworkName(projectID); networkName != "" {
|
||||
if networkName := ProjectNetworkName(projectID); networkName != "" {
|
||||
if err := de.dockerClient.ConnectSelfToNetwork(ctx, networkName); err == nil {
|
||||
probeURL = fmt.Sprintf("http://%s:%d%s", serviceName, port, healthPath)
|
||||
}
|
||||
@@ -456,7 +458,7 @@ func (de *DeploymentEngine) RemoveProjectContainers(ctx context.Context, project
|
||||
|
||||
// RemoveProjectNetwork removes the per-project bridge network if present.
|
||||
func (de *DeploymentEngine) RemoveProjectNetwork(ctx context.Context, projectID string) error {
|
||||
return de.dockerClient.RemoveNetwork(ctx, projectNetworkName(projectID))
|
||||
return de.dockerClient.RemoveNetwork(ctx, ProjectNetworkName(projectID))
|
||||
}
|
||||
|
||||
func replicaIndex(c container.Summary) int {
|
||||
|
||||
Reference in new issue
Block a user