diff --git a/internal/api/instances.go b/internal/api/instances.go index edf4a64..a9bcb43 100644 --- a/internal/api/instances.go +++ b/internal/api/instances.go @@ -33,6 +33,27 @@ func (s *Server) listInstances(w http.ResponseWriter, r *http.Request) { respondError(w, http.StatusInternalServerError, "internal server error") return } + + // Reconcile instance statuses with Docker's actual state. + ctx := r.Context() + for i, inst := range instances { + if inst.ContainerID == "" || inst.Status == "removing" { + continue + } + running, err := s.docker.IsContainerRunning(ctx, inst.ContainerID) + if err != nil { + continue // Docker unreachable, keep stored status. + } + actualStatus := "stopped" + if running { + actualStatus = "running" + } + if inst.Status != actualStatus { + instances[i].Status = actualStatus + _ = s.store.UpdateInstanceStatus(inst.ID, actualStatus) + } + } + respondJSON(w, http.StatusOK, instances) } diff --git a/internal/docker/container.go b/internal/docker/container.go index c835766..352a781 100644 --- a/internal/docker/container.go +++ b/internal/docker/container.go @@ -246,6 +246,15 @@ func (c *Client) ListContainers(ctx context.Context, labelFilters map[string]str return result, nil } +// IsContainerRunning checks if a container is in the "running" state. +func (c *Client) IsContainerRunning(ctx context.Context, containerID string) (bool, error) { + inspectResult, err := c.api.ContainerInspect(ctx, containerID, client.ContainerInspectOptions{}) + if err != nil { + return false, err + } + return inspectResult.Container.State != nil && inspectResult.Container.State.Running, nil +} + // InspectContainerPort returns the host port mapped to a given container port. // This is useful after starting a container with auto-assigned ports. func (c *Client) InspectContainerPort(ctx context.Context, containerID string, containerPort string) (uint16, error) {